如何通过configuration更改pipe理Android上的蓝牙连接?

题:
如何pipe理(连接,读取,写入,断开连接)通过configuration更改持续的蓝牙连接?

首选使用ActionBarSherlock的与设备版本2.2“Froyo”兼容的解决scheme。

问题…

  • BluetoothDeviceBluetoothSocket都不能保留在onSaveState

  • 为了保持我的应用程序响应 ,12秒的阻塞调用BluetoothSocket.connect()必须在一个单独的线程上进行。 启动Runnable是推荐长时间任务的推荐方式,但是尝试恢复configuration更改是一场噩梦。 官方文件指出了三种不同的解决scheme。

    • 使用getLastNonConfigurationInstance() ,这是弃用(严重?!)。

    • 像BluetoothChat示例一样设置android:configChanges="keyboardHidden|orientation" 。 但是,这不包括所有types的configuration更改。

    • 取消并重新启动“ Shelves Example”等任务。 在这种情况下,这可能会浪费另外的12秒。

更新1

  • 进一步的研究导致我asyncTaskLoader ,但似乎这只能完成更新UI,并不能提供更新。

  • BluetoothHDP示例使用服务。 服务似乎侧重于进程间通信,并且需要坚持超出活动的生命周期。 我不需要这些function。

更新2

正如Reuben所指出的那样 , Fragment.setRetainInstance(bool)已经取代了弃用的getLastNonConfigurationInstance() 。 在这一点上,似乎最好的select是使用setRetainInstance(true)创build一个持久的非UI片段。

Solutions Collecting From Web of "如何通过configuration更改pipe理Android上的蓝牙连接?"

有一堆解决scheme。 如果你不使用片段,那么最简单的select是覆盖onRetainNonConfigurationInstance()。 不要介意这个API已经被弃用了,那只是因为他们希望你使用Fragments(公平地说,Fragment.setRetainInstance()使得整个问题变得简单得多了)。 这个API在很长一段时间内都不会去。

我会做的是覆盖onRetainNonConfiguration()返回“this”,即对死亡活动实例的引用,然后从onCreate()复制你需要的对象引用,即:

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

或者你可以使用服务,但我个人不喜欢他们。 毫无疑问,这对于跨进程的东西是有用的,但是否则它们是寻找问题的一个解决scheme。

最后,作为一般规则,您可以安全地将“全局”数据填充到应用程序上下文中。 要做到这一点,你可以inheritanceandroid.app.Application并在清单中使用<application android:name =“MyApp”>属性。 在这里保留对全局静态数据的Application对象的引用也是很有用的,所以AsyncTasks和其他无上下文的代码总是可以进入Application上下文,而无需传递Context参数。

 class MyApp extends Application { ... public static MyApp context; ... @Override public void onCreate() { super.onCreate(); context = this; ... set up global data here ... } ... } 

我将通过使用可处理您的蓝牙连接的Service来解决此问题,并使该服务与本答复中所述的活动对话。

然后,您可以使用ASyncTask来简单地显示/隐藏对话框,并取消/重新启动ASyncTasks,这是由您提到的Shelves Example完成的。

服务是不是真的很可怕,可能是你的问题最好的工具。

切勿将App模型(逻辑或数据)放置在Visual / 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服务,将有助于保留正在运行的任务。

  • 正在运行的后台服务。 哪些活动,片段等可以绑定/解除绑定,并发布命令/请求。 这是App范围内正在运行的进程和数据的推荐位置。

  • 具有setRetainInstance(true)非可视片段。 这里的非可视化意味着它是一个附加到Activity但不显示任何视图的虚拟片段。 它只是用作活动的可保留对象的持有者。 这被推荐用于活动范围的过程和数据。

您可以尝试使用可以处理所有事情的单例模式 ,并在必要时调用主要活动。

因此,每次调用getInstance时,获取MySingleton对象的实例是一个静态方法。 你可以“存储”所有的蓝牙对象,它不会被破坏和访问从每个活动。

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