从通知启动的活动中,AsyncTask没有在onPostExexute上运行

根菜类

我正在编写一个Android应用,该应用使用AlarmManager在后台检查新消息WakefulBroadcastReceiver接收器启动,IntentService并将AsyncTask用作网络请求(HTTPClient)。

重新启动后,使用BroadcastReceiver侦听来重新启用警报android.intent.action.BOOT_COMPLETED

当我的主Activity的onCreate方法使用AsyncTask加载完整的邮件内容时会发生问题,但仅在某些情况下:

java.lang.RuntimeException: Handler (android.os.AsyncTask$InternalHandler) {4139f618} sending message to a Handler on a dead thread

doInBackground执行并返回String带有有效内容的,但是,如果不执行onPostExecute,则说明会上升。

有几种方案:

  1. 我从启动器-> WORKS启动该应用程序
  2. 该应用程序已像(1)一样启动,发送到后台,然后出现一条消息。点击通知,活动开始-> WORKS
  3. 该应用程序已像(1)一样启动,发送到后台并且设备已重启。消息到达,点击通知,活动开始-> EXCEPTION

问题:如何解决此问题,而又不会在UI线程上进行网络请求而使开发人员陷入困境?

在寻找解决方案时,我发现在AsyncTask中未调用onPostExecute(处理程序运行时异常),但是“ sdw”和“ Jonathan Perlow”的解决方案都没有改变。

ServerQuery:

public abstract class ServerQuery extends AsyncTask<Void, Void, String> {
    protected Context context;

    String user = "ERR";
    String pin = "ERR";
    String cmd = "ERR";

    ServerQuery(Context context, String _user, String _pin, String _cmd) {
        this.context = context;
        user = _user;
        pin = _pin;
        cmd = _cmd;
    }

    private ServerQuery() {
    }

    @Override
    protected String doInBackground(Void... params) {
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair(context.getString(R.string.post_client), context.getString(R.string.post_client_app)));
        nameValuePairs.add(new BasicNameValuePair(context.getString(R.string.post_user), user));
        nameValuePairs.add(new BasicNameValuePair(context.getString(R.string.post_pin), pin));
        nameValuePairs.add(new BasicNameValuePair(context.getString(R.string.post_cmd), cmd));
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost("http://[my server hostname]/index.php");
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        } catch (UnsupportedEncodingException e) {
            return "ERR";
        }
        HttpResponse httpResponse = null;
        try{
            httpResponse = httpClient.execute(httpPost);
        }catch (Exception e) {
            return "ERR";
        }
        HttpEntity httpEntity = httpResponse.getEntity();
        InputStream inputStream = null;
        try {
            inputStream = httpEntity.getContent();
        } catch (IOException e) {
            return "ERR";
        }
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder stringBuilder = new StringBuilder();
        String s = null;
        try {
            while ((s = bufferedReader.readLine()) != null) {
                stringBuilder.append(s);
            }
        } catch (IOException e) {
            return "ERR";
        }
        try {
            inputStream.close();
        } catch (IOException e) {
            return "ERR";
        }
        return stringBuilder.toString();
    }
}

lastID:

public class lastID extends ServerQuery {

    Integer lastid, savedid;

    lastID(Context context, String _user, String _pin, String _cmd) {
        super(context, _user, _pin, _cmd);
        lastid = -1;
    }

    @Override
    protected void onPostExecute(final String success) {
        if(success.equals("ERR") || success.length() < 1) {
            Toast.makeText(context, context.getString(R.string.server_no_connection), Toast.LENGTH_LONG).show();
        } else {
            String content[] = success.split("(;)");
            if(content.length == 2) {
                lastid = Integer.parseInt(content[0]);
                SharedPreferences sharedPreferences = context.getSharedPreferences(context.getString(R.string.settings_filename), 0);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                savedid = sharedPreferences.getInt(context.getString(R.string.post_lastid), -1);
                if (lastid > savedid) { // NEUES ANGEBOT!
                    editor.putInt(context.getString(R.string.post_lastid), lastid);
                    editor.commit();
                    // Benachrichtung
                    NotificationCompat.Builder notific = new NotificationCompat.Builder(context);
                    notific.setContentTitle(context.getString(R.string.notify_title));
                    notific.setContentText(content[1]);
                    notific.setSmallIcon(R.drawable.ic_notify);
                    notific.setAutoCancel(false);
                    notific.setPriority(NotificationCompat.PRIORITY_HIGH);
                    notific.setTicker(content[1]);
                    notific.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS);

                    Intent resultIntent = new Intent(context, MainActivity.class);
                    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
                    stackBuilder.addParentStack(MainActivity.class);
                    stackBuilder.addNextIntent(resultIntent);
                    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_CANCEL_CURRENT);
                    notific.setContentIntent(resultPendingIntent);

                    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
                    notificationManager.notify(lastid, notific.build());
                }
            }
        }
    }
}

MainActivity onCreate:

[ loading shared preferences, setting onclicklisteners ]
angebot = new Angebot(this, getApplicationContext(), user, pin, getString(R.string.post_cmd_viewAngebot));
angebot.execute((Void) null);

Angebot类似于lastID,但它使用String来填充TextView编辑1:Angebot:

public class Angebot extends ServerQuery {

    protected Activity activity;

    protected TextView datumView;
    // more TextView s
    protected Button hungerButton;

    Angebot(Activity activity, Context context, String _user, String _pin, String _cmd) {
        super(context, _user, _pin, _cmd);
        this.activity = activity;

        datumView = (TextView) this.activity.findViewById(R.id.datum);
        // finding all other TextView s
    }

    @Override
    protected void onPreExecute() {
        showProgress(true);
    }

    @Override
    protected void onPostExecute(final String success) {
        Log.v(C.TAG_ALARMESSEN, "Angebot.onPostExecute");
        showProgress(false);
        if(success.equals("ERR") || success.length() < 1) {
            Toast.makeText(activity.getApplicationContext(), context.getString(R.string.server_no_connection), Toast.LENGTH_LONG).show();
        } else {
            String content[] = success.split("(;)");
                // put each content string in a TextView
            } else {
                Toast.makeText(context, context.getString(R.string.err02s), Toast.LENGTH_LONG).show(); // nicht angemeldet
            }
        }
    }

    @Override
    protected void onCancelled() {
        showProgress(false);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    public void showProgress(final boolean show) {
        final View progressView = activity.findViewById(R.id.login_progress);
        progressView.setVisibility(show ? View.VISIBLE : View.GONE);
    }
}

编辑2:堆栈跟踪:

java.lang.RuntimeException: Handler (android.os.AsyncTask$InternalHandler) {4139f618} sending message to a Handler on a dead thread
            at android.os.MessageQueue.enqueueMessage(MessageQueue.java:196)
            at android.os.Handler.sendMessageAtTime(Handler.java:473)
            at android.os.Handler.sendMessageDelayed(Handler.java:446)
            at android.os.Handler.sendMessage(Handler.java:383)
            at android.os.Message.sendToTarget(Message.java:363)
            at android.os.AsyncTask.postResult(AsyncTask.java:300)
            at android.os.AsyncTask.access$400(AsyncTask.java:156)
            at android.os.AsyncTask$2.call(AsyncTask.java:264)
            at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
            at java.util.concurrent.FutureTask.run(FutureTask.java:137)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
            at java.lang.Thread.run(Thread.java:856)
伊曼纽尔·莫克林

我认为这里提到的AsyncTask错误的解决方法是:在这种情况下,不在AsyncTask中调用onPostExecute(处理程序运行时异常)也可以,但是根据OP却不起作用。

除了建议解决此问题外,我建议改用AsyncTaskLoader。关于AsyncTaskLoader与AsyncTask的区别(主要是优点),有很多文章。这只是两个(好的)示例):http : //www.javacodegeeks.com/2013/01/android-loaders-versus-asynctask.htmlhttp://www.androiddesignpatterns.com/2012/07/loaders- and-loadermanager-background.html

AsyncTaskLoader的主要优点是,它们与启动它的Activity或Fragment的生命周期同步,并且可以优雅地处理配置更改(与AsyncTasks不同)。

这是实现它的方法。首先,您需要AsyncLoaderClass:

class ServerQuery extends AsyncTaskLoader<String> {
    String mResult;

    public ServerQuery(Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        if (mResult == null) {
            forceLoad();    // no data yet -> force load it
        }
        else {
            deliverResult(mResult); // already got the data -> deliver it
        }
    }

    @Override
    public String loadInBackground() {
        // load your data...

        return mResult; // return the loaded data
    }

    @Override
    public void cancelLoadInBackground() {
        // do whatever it takes to stop loading
    }
}

将doInBackground方法中的内容替换为“ //加载数据...”部分。实际的AsyncTaskLoader就是所有这些。如您所见,没有与onPostExecute等效的东西,这就是AsyncTaskLoader的优点,它在那里可以加载数据,仅此而已。由于AsyncTask尝试更新onPostExecute上的ui而发生的所有问题均已消失。

现在,onPostExecute中的逻辑完全位于启动加载程序的Activity / Fragment中。这是您的操作方式:

LoaderManager loaderMgr = getLoaderManager();
loaderMgr.initLoader(0, null, this);

代表LoaderManager.LoaderCallbacks,这意味着您必须在片段/活动中实现该接口,如下所示:

@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
    return new ServerQuery(this);
}

@Override public void onLoaderReset(Loader<String> loader) {}

@Override
public void onLoadFinished(Loader<String> loader, String data) {
    // here goes your code to update the ui (previously onPostExecute);
}

onCreateLoader只是创建您的加载器(在这种情况下为ServerQuery),此后将由LoaderManager管理。当数据传递到片段/活动中时,将调用onLoadFinished,从而允许您更新ui。您可以查看我的其他答案之一,以获取有关装载机的更多信息,以帮助您了解它们的工作方式:https : //stackoverflow.com/a/20916507/534471特别是有关配置更改的部分可能会有所帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

没有启动新活动的通知操作?

来自分类Dev

单击通知是否没有启动预期的活动?

来自分类Dev

单击通知是否没有启动预期的活动?

来自分类Dev

是否可以通知我已发送了活动意图,而没有注册要启动的活动

来自分类Dev

在没有NFC的设备上启动活动时,错误:NullPointerException

来自分类Dev

在Kotlin的AsyncTask中启动新活动

来自分类Dev

在没有SqlDependency的查询通知上运行存储过程

来自分类Dev

如果服务正在运行,则从通知中更新的UI来启动活动

来自分类Dev

我的应用程序中没有出现启动屏幕,第二个活动运行后只有空白的白色屏幕出现

来自分类Dev

如何将AsyncTask添加到没有活动的公共类中?

来自分类Dev

在没有BroadcastReceiver的情况下在BOOT_COMPLETED上启动活动

来自分类Dev

通过安全锁定屏幕上的通知启动活动

来自分类Dev

启动时启动服务而没有活动

来自分类Dev

C#-当站点上没有活动时,Quartz Scheduler停止运行

来自分类Dev

添加MapView后,如果没有MapView,调用Instabug将无法在“活动”上运行

来自分类Dev

如果活动已经在运行,则在单击带有未决意图的通知时启动活动将调用哪个函数

来自分类Dev

PHP / PDO如何在类中启动重用连接以解决“没有活动的交易”错误

来自分类Dev

通知未在Android中通过操作启动活动

来自分类Dev

Corona中的Admob没有在电话上运行

来自分类Dev

在运行前台服务时从应用启动器和通知启动相同的活动

来自分类Dev

从一个活动启动AsyncTask,在另一个活动中获取结果

来自分类Dev

如果没有启动Edge和IE,为什么我的PC上仍在运行它们?

来自分类Dev

无法启动 Rails 本地主机 - (没有进程在端口 3000 上运行)

来自分类Dev

正在启动Dropbox ... Dropbox没有运行!

来自分类Dev

正在启动Dropbox ... Dropbox没有运行!

来自分类Dev

hrtimer即使没有启动也运行

来自分类Dev

从通知启动活动后返回主活动

来自分类Dev

我怎么在我的Java swing应用程序中推送通知,即使它没有运行?

来自分类Dev

有没有一种方法可以停止在Android检测测试Kotlin(ActivityTestRule)中启动活动

Related 相关文章

  1. 1

    没有启动新活动的通知操作?

  2. 2

    单击通知是否没有启动预期的活动?

  3. 3

    单击通知是否没有启动预期的活动?

  4. 4

    是否可以通知我已发送了活动意图,而没有注册要启动的活动

  5. 5

    在没有NFC的设备上启动活动时,错误:NullPointerException

  6. 6

    在Kotlin的AsyncTask中启动新活动

  7. 7

    在没有SqlDependency的查询通知上运行存储过程

  8. 8

    如果服务正在运行,则从通知中更新的UI来启动活动

  9. 9

    我的应用程序中没有出现启动屏幕,第二个活动运行后只有空白的白色屏幕出现

  10. 10

    如何将AsyncTask添加到没有活动的公共类中?

  11. 11

    在没有BroadcastReceiver的情况下在BOOT_COMPLETED上启动活动

  12. 12

    通过安全锁定屏幕上的通知启动活动

  13. 13

    启动时启动服务而没有活动

  14. 14

    C#-当站点上没有活动时,Quartz Scheduler停止运行

  15. 15

    添加MapView后,如果没有MapView,调用Instabug将无法在“活动”上运行

  16. 16

    如果活动已经在运行,则在单击带有未决意图的通知时启动活动将调用哪个函数

  17. 17

    PHP / PDO如何在类中启动重用连接以解决“没有活动的交易”错误

  18. 18

    通知未在Android中通过操作启动活动

  19. 19

    Corona中的Admob没有在电话上运行

  20. 20

    在运行前台服务时从应用启动器和通知启动相同的活动

  21. 21

    从一个活动启动AsyncTask,在另一个活动中获取结果

  22. 22

    如果没有启动Edge和IE,为什么我的PC上仍在运行它们?

  23. 23

    无法启动 Rails 本地主机 - (没有进程在端口 3000 上运行)

  24. 24

    正在启动Dropbox ... Dropbox没有运行!

  25. 25

    正在启动Dropbox ... Dropbox没有运行!

  26. 26

    hrtimer即使没有启动也运行

  27. 27

    从通知启动活动后返回主活动

  28. 28

    我怎么在我的Java swing应用程序中推送通知,即使它没有运行?

  29. 29

    有没有一种方法可以停止在Android检测测试Kotlin(ActivityTestRule)中启动活动

热门标签

归档