7

質問:
設定を変更しても維持される Bluetooth 接続を管理 (接続、読み取り、書き込み、切断) するにはどうすればよいですか?

ActionBarSherlockを使用して、デバイス バージョン 2.2 "Froyo" と互換性のあるソリューションを優先します。

問題...

  • BluetoothDeviceに保持することも、保持することもBluetoothSocketできませんonSaveState

  • アプリの応答性を維持するには、12 秒間のブロッキング呼び出しBluetoothSocket.connect()を別のスレッドで行う必要があります。長いタスクをスレッド化するための推奨される方法は、開始することRunnableですが、構成の変更を回復しようとするのは悪夢です。公式ドキュメントは、3 つの異なるソリューションを示しています。

    • 非推奨の を使用しますgetLastNonConfigurationInstance()(真剣に?!)。

    • BluetoothChat Sampleandroid:configChanges="keyboardHidden|orientation"のように設定します。ただし、これはすべてのタイプの構成変更を考慮しているわけではありません。

    • の例 のようなタスクをキャンセルして再開します。この場合、さらに 12 秒無駄になる可能性があります。

更新 1

  • さらなる調査により、asyncTaskLoaderにたどり着きましたが、これは完了時にしか UI を更新できず、更新を提供できないようです。

  • BluetoothHDP サンプルはサービスを使用します。サービスは、プロセス間の通信と、アクティビティのライフサイクルを超えて存続する必要性に重点を置いているようです。これらの機能はどちらも必要ありません。

更新 2

Reuben が指摘したように、非推奨のFragment.setRetainInstance(bool)を置き換えましたgetLastNonConfigurationInstance()。現時点では、 を使用して永続的な非 UI フラグメントを作成するのが最善の選択肢のようsetRetainInstance(true)です。

4

4 に答える 4

4

アプリ モデル (ロジックまたはデータ) をビジュアル/UI コンポーネントに配置しないでください。ご覧のとおり、それらは行き来し、変化します。

データ コレクション、ライブ接続、スレッドなど、UI に関連しないものを保持する場所:

  • アプリケーション クラス。他のすべてのコンポーネントのライフサイクルを包み込みます。ほとんどグローバルシングルトンのようです。一時保管にご利用いただけます。

例:

public class App extends Application {

  private static Beer sBeer;

  public static void brbHoldMyBeer(Beer b){
    sBeer = b;
  }

  public static Beer imBackWheresMyBeer(){
    return sBeer;
  }

}

また、Application クラスに静的スレッド Executor サービスを用意すると、実行中のタスクを保持するのに役立ちます。

  • 実行中のバックグラウンド サービス。どのアクティビティ、フラグメントなどにバインド/バインド解除し、コマンド/リクエストを投稿できますか。これは、アプリ全体で実行されているプロセスとデータに推奨される場所です。

  • を含む非ビジュアル フラグメントsetRetainInstance(true)。ここで非視覚的とは、Activity にアタッチされているがビューを表示しないダミー フラグメントであることを意味します。アクティビティの保持可能なオブジェクト ホルダーとして使用されます。これは、アクティビティ全体のプロセスとデータに推奨されます。

于 2013-04-05T18:41:20.933 に答える
2

すべてを処理できるシングルトン パターンを試して、必要なときにメイン アクティビティを呼び出すことができます。

したがって、MySingleton オブジェクトのインスタンスを取得するのは 1 つの静的メソッドであり、getInstance を呼び出すたびに同じインスタンスになります。その中にすべての bluetooth オブジェクトを「保存」できます。破棄されず、各アクティビティからアクセスできません。

public class MySingleton { 
    private static MySingleton instance; 
    public static MySingleton getInstance() { 
        if (null == instance) { 
            instance = new MySingleton(); 
        } 
    return instance; 
} 

    private MySingleton() { 
    } 
}
于 2013-03-31T16:21:43.323 に答える
1

これにはたくさんの解決策があります。フラグメントを使用していない場合、最も簡単なオプションは onRetainNonConfigurationInstance() をオーバーライドすることです。API が非推奨であることを気にしないでください。それは、Fragments を使用することを望んでいるからです (公平を期すために、 Fragment.setRetainInstance() により、この問題全体が常にそうあるべきであることが非常に簡単になります)。この API は、長い間どこにも行きません。

私がしたいことは、onRetainNonConfiguration() をオーバーライドして「this」、つまり死んだ Activity インスタンスへの参照を返し、次に onCreate() から必要なオブジェクト参照をコピーすることです。

Object obj = getLastNonConfigurationInstance();
if (obj != null) {
    MyActivity deadActivity = (MyActivity)obj;
    this.foo = deadActivity.foo;
    this.bar = deadActivity.bar;
    ...
}

または、サービスを使用することもできますが、個人的には嫌いです。間違いなくクロスプロセスの作業に役立ちますが、それ以外の場合は、問題を探すためのソリューションです。

最後に、一般的な順序として、「グローバル」データをアプリケーション コンテキストに安全に詰め込むことができます。これを行うには、android.app.Application をサブクラス化し、マニフェストで <application android:name="MyApp"> 属性を使用します。ここで、Application オブジェクトへの参照をグローバルな静的データに保持しておくと便利です。そのため、AsyncTasks やその他のコンテキストのないコードは、理由もなく Context パラメーターを渡す必要なく、いつでも Application コンテキストにアクセスできます。

class MyApp extends Application {
...

    public static MyApp context;
    ...

    @Override
    public void onCreate() {
        super.onCreate();

        context = this;

        ... set up global data here ...
    }
...
}
于 2013-03-31T16:32:21.910 に答える