2015年7月31日金曜日

FragmentのからActivity/ParentFragmentへのEvent通知

FragmentのからActivity/ParentFragmentへのCallbackにInterfaceの定義とアタッチが面倒くさい!

  • 専用Callback
    • Activity/ParentFragmentでCallback Interface実装
    • FragmentでCallbackの登録
      • onAttachでActivityをCallback Interfaceにキャストして登録
      • getParentFragmenでCallback Interfaceにキャストして登録
        • Fragment側で親を意識しなければならない!!
    • 個々のCallback Interfaceの設計と実装
      • 複数のFragmentの数だけCallbackが必要!!
      • タイプセーフティ?
  • 汎用Callback
    • Activity/ParentFragmentでCallback Interface実装
    • FragmentでCallbackの登録
      • onAttachでActivityをCallback Interfaceにキャストして登録
      • getParentFragmenでCallback Interfaceにキャストして登録
        • Fragment側で親を意識しなければならない!!
    • Callback Interfaceの実装は一つ
      • 汎用化の為、Bundleにオブジェクト格納
        • どのFragmentからのCallbackであるか識別が必要!!
        • Bundleからキー指定してイベント通知内容を取得
  • LocalBroadcastManager
    • Activity/ParentFragmentでIntentFilterを指定してレシーバーを登録
    • FragmentからIntentをブロードキャスト
    • 汎用化の為、IntentのBundleにオブジェクト格納
      • どのFragmentからのCallbackであるか識別が必要!!
      • Bundleからキー指定してイベント通知内容を取得
    • 必ずMainスレッドメッセージの送受信
  • Event Bus (Otto)
    • Activity/ParentFragmentでBusを登録
    • FragmentでBusを登録
    • Activity/ParentFragmentでSubscribeメソッド実装
    • FragmentでProduceメソッドを実装
    • ProduceとSubscribeのインターフェースはPOJOのEventオブジェクト
    • Eventオブジェクトなのでタイプセーフティ
    • デフォルトではMainスレッド以外ではメッセージ送信(Produce)は出来ない。
      • Busインスタンス作成時にThreadEnforcer.ANYを指定すれば、他のスレッドからメッセージ送信できる。
      • しかし、Subscribeメソッドがメッセージ送信時スレッドで実行されてしまいスレッド管理が煩雑
      • runOnUiThread でMainスレッドで実行させる仕組みが必要
    • 何処のクラスからでもメッセージ送信(Produce)で来てしまうので、煩雑化する。
      • DialogFragmentのAlertDialogのOnClickCallbackからActivityに通知できる...
      • 意図しない箇所でSubscribeされる。


    android - LocalBroadcastManager vs using callbacks - Stack Overflow http://stackoverflow.com/questions/13948720/localbroadcastmanager-vs-using-callbacks

    Otto square.github.io/otto/
    Does Otto use weak references to store objects passed to register()?
    https://plus.google.com/101050435280754106754/posts/PGygiXURaTW

    EventBus - torutkの日記 http://d.hatena.ne.jp/torutk/20110407/p1

    2014年10月14日火曜日

    Android Gradle で Nativeライブラリ(.so) を含める方法

    Android Gradle Plugin 0.7.2 からサポートされてた O(≧▽≦)O

    StackOverFlowには、自前タスクを作成する回答ばかりヒットしますが、0.7.2 からサポートされてました!!

    New Build System - Android Tools Project Site http://tools.android.com/tech-docs/new-build-system
    0.7.2

    Note: 0.7.2 requires Java7. This is a mistake. Use 0.7.3 instead.
    • Fix issue with Proguard.
    • Add packagingOptions support in Library projects.
    • Solve issue with local jar when testing library projects.
    • Fix bug with variant.addJavaSourceFoldersToModel
    • Add jniLibs folder to source sets for prebuilt .so files.
    • Lint fixes:
      • fix RTL detector
      • fix HTML report to have valid HTML
    New Samples: ndkJniLib, genFolderApi2

    src/main/jniLibs が標準の配置ディレクトリです。
    変更する場合は、

    sourceSets {
        main {
            jniLibs.srcDirs = ['jniLibs']
        }
    }

    とします。


    以上、覚え書き!

    2013年12月26日木曜日

    ActionBarActivityで finalになったonMenuItemSelectedのソースを追ってみた

    ActionBarActivity#onOptionsItemSelectedのソースを追ってみた。

    android.support.v7.app.ActionBarActivity ActionBarActivityDelegate mImpl; @Override public final boolean onMenuItemSelected(int featureId, android.view.MenuItem item) { if (mImpl.onMenuItemSelected(featureId, item)) { return true; } final ActionBar ab = getSupportActionBar(); if (item.getItemId() == android.R.id.home && ab != null && (ab.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { return onSupportNavigateUp(); } return false; } 5行目で、ActionBarActivityDelegateのonMenuItemSelectedを呼び出している。
    ActionBarActivityDelegateを実装は幾つかのOSレベル毎に分かれているので、 その1つActionBarActivityDelegateBaseを見てみる。

    android.support.v7.app.ActionBarActivityDelegateBase @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if (featureId == Window.FEATURE_OPTIONS_PANEL) { item = MenuWrapperFactory.createMenuItemWrapper(item); } return mActivity.superOnMenuItemSelected(featureId, item); } ActionBarActivityのsuperOnMenuItemSelectedを呼んでいる。

    android.support.v7.app.ActionBarActivity boolean superOnMenuItemSelected(int featureId, MenuItem menuItem) { return super.onMenuItemSelected(featureId, menuItem); } ActionBarActivityの親クラスFragmentActivityのonMenuItemSelectedを呼んでいる。

    android.support.v4.app.FragmentActivity /** * Dispatch context and options menu to fragments. */ @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if (super.onMenuItemSelected(featureId, item)) { return true; } switch (featureId) { case Window.FEATURE_OPTIONS_PANEL: return mFragments.dispatchOptionsItemSelected(item); case Window.FEATURE_CONTEXT_MENU: return mFragments.dispatchContextItemSelected(item); default: return false; } } 6行目の親クラスActivityActivityのonMenuItemSelectedを呼んでいる。
    メニューが処理されなかったら、Fragmentのメニューを呼び出している。
    • Window.FEATURE_OPTIONS_PANEL - ActionBarや昔のメニューパネル
    • Window.FEATURE_CONTEXT_MENU - ロングタップで表示されるコンテキストメニュー


    android.app.Activity public boolean onMenuItemSelected(int featureId, MenuItem item) { CharSequence titleCondensed = item.getTitleCondensed(); switch (featureId) { case Window.FEATURE_OPTIONS_PANEL: // Put event logging here so it gets called even if subclass // doesn't call through to superclass's implmeentation of each // of these methods below if(titleCondensed != null) { EventLog.writeEvent(50000, 0, titleCondensed.toString()); } if (onOptionsItemSelected(item)) { return true; } if (mFragments.dispatchOptionsItemSelected(item)) { return true; } if (item.getItemId() == android.R.id.home && mActionBar != null && (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) { if (mParent == null) { return onNavigateUp(); } else { return mParent.onNavigateUpFromChild(this); } } return false; case Window.FEATURE_CONTEXT_MENU: if(titleCondensed != null) { EventLog.writeEvent(50000, 1, titleCondensed.toString()); } if (onContextItemSelected(item)) { return true; } return mFragments.dispatchContextItemSelected(item); default: return false; } } メニューは、12行目でonOptionsItemSelectedを呼び出し。 コンテキストメニューは、32行目でonContextItemSelectedを呼び出し。


    リファレンスのOnMenuItemSelectedの記述
    Default implementation of onMenuItemSelected(int, MenuItem) for activities. This calls through to the new onOptionsItemSelected(MenuItem) method for the FEATURE_OPTIONS_PANEL panel, so that subclasses of Activity don't need to deal with feature codes.

    この通り、onOptionsItemSelectedをオーバーライドしてメニューの処理を実装を行なうのが正しいようだ。

    コンテキストメニューはonContextItemSelectedをオーバーライドして処理を実装を行なうのが正しいようだ。


    Honycombから、Activity#onMenuItemSelectedにはFragmentやActionBarのメニュー処理が行なわれてるためオーバーライドは注意が必要。

    2013年12月25日水曜日

    ActionBarActivityのOnMenuItemSelectedはオーバーライドできない。

    Supoport Libraryに追加されたandroid-support-v7-appcompatのActionBarActivityのOnMenuItemSelectedはオーバーライドできない。



    OnMenuItemSelectedはfinalメソッドとなっている。
    代わりに、
    onOptionsItemSelectedをオーバーライドして使用します。

    リファレンスのOnMenuItemSelectedの記述は以下の通りです。
    Default implementation of onMenuItemSelected(int, MenuItem) for activities. This calls through to the new onOptionsItemSelected(MenuItem) method for the FEATURE_OPTIONS_PANEL panel, so that subclasses of Activity don't need to deal with feature codes.
     そもそも、OnMenuItemSelectedを実装しているのが間違っていた?

    2013年5月16日木曜日

    Android SDK 22 では、Build Toolsが必要になったようです。

    今朝リリースされた Android SDK 22について注意

    このバージョンより Android SDK Build-toolsが必要になりました。 

    インストールしていないと、
    ant debug/release 実行に、以下のようなメッセージが出て、ビルドできません。 {android-sdk}/tools/ant/build.xml:479: SDK does not have any Build Tools installed.

     Eclipseでも、
    Android Tools > Export Signed/Unsigned Application Package... を実行すると同じようなエラーダイアログが表示されました。

     

    SDK 22からToolsに Android SDK Build-tools が増えてるのでインストールしておくように!