Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/200.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果使用辅助线程,如何防止ANR?_Android - Fatal编程技术网

Android 如果使用辅助线程,如何防止ANR?

Android 如果使用辅助线程,如何防止ANR?,android,Android,我的应用程序在第一次启动时从原始文件下载并解压缩一些数据所有长时间运行的进程都是在后台线程服务中执行的,因此我认为没有明显的理由进行ANR(请纠正我) 使用androidResultReceiver将进度和状态消息发送到activity: private ResultReceiver receiver; public void sendProgress(int percent) { Bundle data = new Bundle(); data.putInt(

我的应用程序在第一次启动时从原始文件下载并解压缩一些数据所有长时间运行的进程都是在后台线程服务中执行的,因此我认为没有明显的理由进行ANR(请纠正我)

使用android
ResultReceiver
将进度和状态消息发送到activity:

private ResultReceiver receiver;

public void sendProgress(int percent) {
        Bundle data = new Bundle();
        data.putInt(InstallResultReceiver.DATA_PROGRESS, percent);
        receiver.send(InstallResultReceiver.RESULT_PROGRESS, data);
    }
该活动仅显示ProgressDialog并更新百分比和状态消息

问题是,当下载/安装ANR时,Android会发送信号6(中止)。我怎样才能防止/绕过这一点

ANR的原因是亚马逊应用程序内购买计费接收器,但我相信这并不重要

日志:

文件说明

警告:默认情况下,服务与声明它的应用程序在同一进程中运行,并且在该应用程序的主线程中运行。因此,如果您的服务在用户与来自同一应用程序的活动交互时执行密集或阻塞操作,则该服务将降低活动性能。为避免影响应用程序性能,您应该在服务内启动一个新线程。

此外,您可以通过打开调试视图并查看线程的状态来检查eclipse中线程的状态


我有点困惑,为什么您选择在
AsyncTask
IntentService
上使用服务,后者负责为您创建非ui线程。

onStart命令在应用程序的主线程中调用。看一看。相反,如果您使用IntentService,您应该重写onHandleIntent(Intent Intent),它实际上在工作线程中被调用。

很抱歉没有发布完整的源代码,原因就在其中: 我在
ResultReceiver.onReceiveResult()中处理服务的结果。这个问题是通过使用Handler解决的,所以我只需要将处理放在可运行队列中。此外,我还减少了收到每个意图后的状态保存调用计数(这减少了ui线程上的调用计数),并最终保存了一次

private Handler handler = new Handler();

/**
 *
 */
private class ReceiveResultRunnable implements Runnable {

    private int resultCode;
    private Bundle resultData;

    public ReceiveResultRunnable(int resultCode, Bundle resultData) {
        this.resultCode = resultCode;
        this.resultData = resultData;
    }

    public void run() {
        switch (resultCode) {
            case RESULT_STARTED:
                listener.onStarted();
                break;

            case RESULT_MESSAGE:
                String message = resultData.getString(DATA_MESSAGE);
                listener.onMessage(message);
                break;

            case RESULT_PROGRESS:
                int progress = resultData.getInt(DATA_PROGRESS);
                listener.onProgress(progress);
                break;

            case RESULT_ERROR:
                Throwable t = (Throwable) resultData.getSerializable(DATA_ERROR);
                listener.onError(t);
                break;

            case RESULT_OK:
                int version = resultData.getInt(DATA_REPOSITORY_VERSION);
                listener.onFinished(version);
                break;

            // ...

        }
    }
}

@Override
protected void onReceiveResult(final int resultCode, final Bundle resultData) {
    super.onReceiveResult(resultCode, resultData);

    handler.post(new ReceiveResultRunnable(resultCode, resultData));
}

发布工作线程代码。并检查您的操作是否在任何地方阻止ui,它不会将其作为服务阻止,并且它没有访问ui4ntoine的权限,但服务本身在ui线程中运行,并且有访问ui线程的权限。您确定没有保留线程中的长时间同步(发送者){}吗?可能新的请求被发送到您的服务,并且在这个同步语句中被阻止(因为它被锁定在您的线程中)。@doctordrive。是的,线程从主线程开始。这是唯一一件事,它不会影响这样的结果。我认为在提供的代码中,长任务放在InitThread中。您还没有提供InitThread(job)的实现,因此这里没有人能够帮助您进一步改进服务。在重新创建活动时,服务不会停止,所以我不需要在旋转状态之间传递AsyncTask。IntentService一个接一个地处理意图(就像它是一个队列),而这不是我想要的。通过将AsyncTask放在保留的片段中,您可以绕过此限制。线程run()impl相当大,在我的问题IMHO中它并不重要,因为它在后台线程上执行所有操作,并且不阻塞主线程。它发送结果的方式可能很重要,这就是我提供返回结果代码的原因。它的功能与我的服务完全相同,因此不需要使用IntentService来避免ANR
04-04 13:01:51.016: DEBUG/ActivityInstallListener(1912): on started INSTALL ArmstrongNumber c (1)
04-04 13:01:53.695: DEBUG/ActivityInstallListener(1912): saved repository (9233 bytes)
04-04 13:01:53.695: DEBUG/ActivityInstallListener(1912): on started INSTALL HarmonicNumberSeries c (1)
04-04 13:01:53.885: ERROR/ActivityManager(275): ANR in name.mycompany.android.myapp
        Reason: Broadcast of Intent { act=com.amazon.inapp.purchasing.NOTIFY flg=0x10000010 pkg=name.mycompany.android.myapp cmp=name.mycompany.android.myapp/com.amazon.inapp.purchasing.ResponseReceiver (has extras) }
        Load: 6.71 / 6.75 / 3.23
        CPU usage from 0ms to 5942ms later:
        59% 1912/name.mycompany.android.myapp: 50% user + 8.4% kernel / faults: 809 minor
        24% 275/system_server: 18% user + 6.3% kernel / faults: 1131 minor
        4% 29/mmcqd: 0% user + 4% kernel
        0.6% 505/com.android.phone: 0.4% user + 0.2% kernel / faults: 150 minor
        1% 47/adbd: 0% user + 1% kernel
        0% 519/com.amazon.tcomm: 0% user + 0% kernel / faults: 135 minor
        0% 1715/com.amazon.client.metrics: 0% user + 0% kernel / faults: 236 minor
        0% 12/pdflush: 0% user + 0% kernel
        0.8% 40/mediaserver: 0.1% user + 0.6% kernel
        0% 552/com.amazon.imp: 0% user + 0% kernel / faults: 123 minor
        0.1% 909/com.android.systemui: 0% user + 0% kernel / faults: 104 minor
        0% 459/com.lab126.softkeybar: 0% user + 0% kernel / faults: 110 minor
        0% 539/com.android.providers.downloads: 0% user + 0% kernel / faults: 99 minor
        0.3% 545/android.process.media: 0.1% user + 0.1% kernel / faults: 167 minor
        0% 988/com.nuance.swype.input: 0% user + 0% kernel / faults: 97 minor
        0.5% 13/kswapd0: 0% user + 0.5% kernel
        0.1% 319/logcat: 0% user + 0.1% kernel / faults: 20 minor
        0.3% 1343/com.amazon.ags.app: 0.3% user + 0% kernel / faults: 174 minor
        0% 1//init: 0% user + 0% kernel / faults: 85 minor
        0% 1944/com.amazon.mas.test: 0% user + 0% kernel / faults: 19 minor
        100% TOTAL: 73% user + 25% kernel + 0.1% irq + 0.1% softirq
        CPU usage from 5132ms to 5817ms later:
        62% 1912/name.mycompany.android.myapp: 56% user + 6.4% kernel / faults: 12 minor
        35% 1912/ndroid.myapp: 35% user + 0% kernel
        33% 1957/Thread-208: 22% user + 11% kernel
        1.6% 1919/Compiler: 1.6% user + 0% kernel
        15% 275/system_server: 5.7% user + 10% kernel / faults: 1 minor
        11% 293/ActivityManager: 4.3% user + 7.2% kernel
        13% 29/mmcqd: 0% user + 13% kernel
        0.7% 12/pdflush: 0% user + 0.7% kernel
        1.4% 40/mediaserver: 0% user + 1.4% kernel
        1.4% 40/mediaserver: 0% user + 1.4% kernel
        0.4% 47/adbd: 0% user + 0.4% kernel
        0.4% 47/adbd: 0% user + 0.4% kernel
        100% TOTAL: 62% user + 35% kernel + 1.4% irq
04-04 13:01:53.925: INFO/ActivityManager(275): Tablet:Platform:package=name.mycompany.android.myapp;DV;1,event=app-anr;DV;1:NR
04-04 13:01:53.925: INFO/Process(275): Sending signal. PID: 1912 SIG: 6
private Handler handler = new Handler();

/**
 *
 */
private class ReceiveResultRunnable implements Runnable {

    private int resultCode;
    private Bundle resultData;

    public ReceiveResultRunnable(int resultCode, Bundle resultData) {
        this.resultCode = resultCode;
        this.resultData = resultData;
    }

    public void run() {
        switch (resultCode) {
            case RESULT_STARTED:
                listener.onStarted();
                break;

            case RESULT_MESSAGE:
                String message = resultData.getString(DATA_MESSAGE);
                listener.onMessage(message);
                break;

            case RESULT_PROGRESS:
                int progress = resultData.getInt(DATA_PROGRESS);
                listener.onProgress(progress);
                break;

            case RESULT_ERROR:
                Throwable t = (Throwable) resultData.getSerializable(DATA_ERROR);
                listener.onError(t);
                break;

            case RESULT_OK:
                int version = resultData.getInt(DATA_REPOSITORY_VERSION);
                listener.onFinished(version);
                break;

            // ...

        }
    }
}

@Override
protected void onReceiveResult(final int resultCode, final Bundle resultData) {
    super.onReceiveResult(resultCode, resultData);

    handler.post(new ReceiveResultRunnable(resultCode, resultData));
}