Android的线程VS VS的AsyncTask从IntentService BLE onCharacteristicChanged称为() [英] Android Thread vs AsyncTask vs IntentService called from BLE onCharacteristicChanged()

查看:445
本文介绍了Android的线程VS VS的AsyncTask从IntentService BLE onCharacteristicChanged称为()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我(通过通知每62ms)接收BLE数据的Andr​​oid应用程序。该应用程序可以通过一个的BufferedWriter将文件保存数据。在每次onCharacteristicChanged()回调,我打电话要么是AsyncTask的,螺纹或IntentService做一个文件写入,如果用户启用了文件保存。

本的AsyncTask似乎很好地工作。但该文档说执行必须在UI线程调用,而我从BLE回调调用它。那是一个问题吗?我应该如何解决?

使用线程导致此错误:GKI_exception出缓冲器的 HTTPS ://$c$c.google.com/p/android/issues/detail ID = 65455 (除了我的code未扫描,但收到通知),如果文件保存很长,我?需要电源循环的Nexus 7(应用程序和BLE变得完全没有反应)。为什么不能线程工作,我该如何解决?

该IntentService永不熄灭的onHandleIntent()。什么是这里的问题是什么?

下面是一些code:

  ...
_context = this.getApplicationContext();
...
私人BluetoothGattCallback mGattCallback =新BluetoothGattCallback(){
...
@覆盖
公共无效onCharacteristicChanged(GATT BluetoothGatt,BluetoothGattCharacteristic特性){
...
INT模式= 1;
如果(模式== 0)//的AsyncTask
    新doFileWriteTask()执行(strBuild.toString());
否则如果(模式== 1)//螺纹
{
    最终字符串str = strBuild.toString();
    新主题(新的Runnable接口(){
        公共无效的run(){
           尝试{
               _writer.write(STR);
           }赶上(例外五){
               e.printStackTrace();
           }
        }
    })。开始();
}
否则如果(模式== 2)// intentService
{
    意图mServiceIntent =新意图(_context,writeFileService.class);
    mServiceIntent.putExtra(富,strBuild.toString());
    startService(mServiceIntent);
}
}
...
};私有类doFileWriteTask扩展的AsyncTask<弦乐,太虚,太虚> {
@覆盖
保护无效doInBackground(串...字符串){
    尝试{
        _writer.write(串[0]);
    }赶上(例外五){
        e.printStackTrace();
    }
    返回null;
}私有类writeFileService扩展IntentService {
    公共writeFileService(){
        超级(writeFileService);
    }    @覆盖
    保护无效onHandleIntent(意向workIntent){
        字符串dataString = workIntent.getStringExtra(富);
        尝试{
            _writer.write(dataString);
        }赶上(例外五){
           e.printStackTrace();
        }
    }
}
...


解决方案

  

但是文档说执行必须在UI线程调用,而我从BLE回调调用它。那是一个问题吗?我应该如何解决?


该框架触发了同一个线程它是从所谓的(presumed是主线程)在的AsyncTask 回调方法。它并没有真正影响到背景的工作,但你可以看到的问题,如果你开始尝试使用 onPostExecute()等等。 的AsyncTask 可能是不从,你就不用管了一个线程调用的最佳选择。


  

为什么不线程工作,我该如何解决?


我不能说究竟为什么你仍然看到错误,通过产卵一系列私人非同步线程可能会导致其他头痛。如果你想使用一个工作线程,更好的选择是使用一个 HandlerThread ,您可以用张贴到您的事件回调的处理器,是这样的:

  ...
_workerThread =新HandlerThread(工人);
_workerThread.start();
_handler =新的处理程序(_workerThread.getLooper(),新Handler.Callback(){
        @覆盖
        公共布尔的handleMessage(消息MSG){
            字符串str =(字符串)msg.obj;
            _writer.write(STR);            返回true;
        }
});
...@覆盖
公共无效onCharacteristicChanged(GATT BluetoothGatt,BluetoothGattCharacteristic特性){
    ...
    消息MSG = Message.obtain(_handler,0,strBuild.toString());
    _handler.sendMessage(MSG);
    ...
}

这解决方案是相当多的code,但由于写的频率这可能是最有效的选择。


  

该IntentService永不熄灭的onHandleIntent()。有什么问题吗?


您应该pretty很多从未实现最高级别的Andr​​oid组件(活动,服务,内容提供商,接收器)作为一个内部类,因为它们在你的清单中声明,以及(对于内部的XML语法类是丑陋的)。如果您的服务没有在清单匹配的条目,那么你将永远不会看到它开始。你可能想看看使用服务的文档。

在最低限度,一个服务写成一个内部类必须公共静态工作。否则,该框架还看不出来,并使用默认的构造函数(非静态内部类惹构造函数)不能实例化。除非你调用 startService()现在在try / catch里面,我很惊讶,它不崩溃,当您尝试此。

IntentService 可能是最简单的你三个选择,因为它是最解耦和框架会处理排队的工作拆了线,当所有传入的工作完成的。

I have an Android app from which I receive BLE data (every 62ms via notifications). The app can save data via a BufferedWriter to a file. Upon each onCharacteristicChanged() callback, I call either an AsyncTask, Thread or an IntentService to do a file write if the user enabled file save.

The AsyncTask seems to work fine. But the docs say execute must be invoked on the UI thread, and I'm calling it from the BLE callback. Is that a problem? And how should I fix it?

Using Thread causes this error: GKI_exception out of buffers https://code.google.com/p/android/issues/detail?id=65455 (except my code is not scanning but receiving notifications) and if the file save is long, I need to power cycle the Nexus 7 (the app and BLE become totally unresponsive). Why does the Thread not work and how can I fix it?

The IntentService never goes to the onHandleIntent(). What are the issues here?

Here is some code:

...
_context = this.getApplicationContext();
...
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
...
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
...
int mode = 1;
if (mode==0) // Asynctask
    new doFileWriteTask().execute(strBuild.toString());
else if (mode==1)     // Thread
{
    final String str = strBuild.toString();
    new Thread(new Runnable() {
        public void run() {
           try {
               _writer.write(str);
           } catch (Exception e) {
               e.printStackTrace();
           }
        }
    }).start();
}
else if (mode==2)   // intentService
{
    Intent mServiceIntent = new Intent(_context, writeFileService.class);
    mServiceIntent.putExtra("foo", strBuild.toString());
    startService(mServiceIntent);
}
}
...
};

private class doFileWriteTask extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... strings) {
    try {
        _writer.write(strings[0]);              
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

private class writeFileService extends IntentService {
    public writeFileService() {
        super("writeFileService");
    }

    @Override
    protected void onHandleIntent(Intent workIntent) {
        String dataString = workIntent.getStringExtra("foo"); 
        try {
            _writer.write(dataString);
        } catch (Exception e) {
           e.printStackTrace();
        }           
    }
}
...

解决方案

But the docs say execute must be invoked on the UI thread, and I'm calling it from the BLE callback. Is that a problem? And how should I fix it?

The framework triggers the AsyncTask callback methods on the same thread it was called from (presumed to be the main thread). It doesn't really affect the background work, but you could see problems if you started trying to use onPostExecute() and the like. AsyncTask probably isn't the best choice to be called from a thread that you don't have control over.

Why does the Thread not work and how can I fix it?

I can't say exactly why you are still seeing errors, through spawning a series of private unsynchronized threads will probably lead to other headaches. If you want to use a single worker thread, a better choice would be to use a single HandlerThread that you can post to from your event callbacks using a Handler, something like:

…
_workerThread = new HandlerThread("Worker");
_workerThread.start();
_handler = new Handler(_workerThread.getLooper(), new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            String str = (String) msg.obj;
            _writer.write(str);

            return true;
        }
});
…

@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
    …
    Message msg = Message.obtain(_handler, 0, strBuild.toString());
    _handler.sendMessage(msg);
    …
}

That solution is quite a bit more code, but given the frequency of writes this is probably the most efficient choice.

The IntentService never goes to the onHandleIntent(). What are the issues here?

You should pretty much never implement a top level Android component (activity, service, content provider, receiver) as an inner class, because they have to be declared in your manifest as well (and the XML syntax for inner classes is ugly). If your service does not have a matching entry in the manifest, then you will never see it start. You might want to have a look at the docs on using services.

At a minimum, a Service written as an inner class must be public static to work. Otherwise the framework cannot see it and cannot instantiate it using a default constructor (non-static inner classes mess with the constructor). Unless you are calling startService() inside of a try/catch right now, I'm surprised it isn't crashing when you attempt this.

IntentService is probably the simplest of your three choices because it is the most decoupled and the framework will handle queueing up work and tearing down the threads when all the incoming work is done.

这篇关于Android的线程VS VS的AsyncTask从IntentService BLE onCharacteristicChanged称为()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆