Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/221.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.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 异步任务在按下backbutton时崩溃。_Android_Android Asynctask - Fatal编程技术网

Android 异步任务在按下backbutton时崩溃。

Android 异步任务在按下backbutton时崩溃。,android,android-asynctask,Android,Android Asynctask,当暂停/删除调用片段时,异步任务会发生什么情况?我假设任务完成了,但如果有人能证实这一点,那就太好了。我正试图找到一个解决我撞车的办法 我有一个异步任务,它是一个递归图像加载程序。图像加载程序是为其加载图像的listFragment的内部类。图像加载器工作正常,除非我在它加载完所有图像之前按下后退按钮。当我在所有图像加载完成之前按下后退按钮时,应用程序崩溃。我觉得映像加载程序无法访问适配器,但我不确定是否正确解决了此问题。我不确定如何在异步任务中解决此问题。如果有人能帮我。甚至从我的脑海中蹦出一

当暂停/删除调用片段时,异步任务会发生什么情况?我假设任务完成了,但如果有人能证实这一点,那就太好了。我正试图找到一个解决我撞车的办法

我有一个异步任务,它是一个递归图像加载程序。图像加载程序是为其加载图像的listFragment的内部类。图像加载器工作正常,除非我在它加载完所有图像之前按下后退按钮。当我在所有图像加载完成之前按下后退按钮时,应用程序崩溃。我觉得映像加载程序无法访问适配器,但我不确定是否正确解决了此问题。我不确定如何在异步任务中解决此问题。如果有人能帮我。甚至从我的脑海中蹦出一个想法,让我以不同的方式思考

任何帮助都会很棒。谢谢你抽出时间来看我

图像加载器

private class ImageLoaderTask extends
        AsyncTask<HashMap<String, Object>, Void, HashMap<String, Object>> {

    @Override
    protected HashMap<String, Object> doInBackground(
            HashMap<String, Object>... hm) {
        InputStream in = null;

        String url = (String) hm[0].get("image");
        int pos = (Integer) hm[0].get("pos");
        url = "http://kzfr.org/u/img/small/" + url;
        URL mUrl;

        try {
            mUrl = new URL(url);
            URLConnection urlConnect = (URLConnection) mUrl
                    .openConnection();
            in = urlConnect.getInputStream();

            File cacheDirectory = getSherlockActivity().getBaseContext()
                    .getCacheDir();

            File tmp = new File(cacheDirectory.getPath() + "/kzfr_small"
                    + pos + ".png");

            FileOutputStream fOut = new FileOutputStream(tmp);

            Bitmap b = BitmapFactory.decodeStream(in);
            b.compress(Bitmap.CompressFormat.PNG, 100, fOut);
            fOut.flush();
            fOut.close();

            HashMap<String, Object> hmBmp = new HashMap<String, Object>();
            hmBmp.put("blank_start", tmp.getPath());
            hmBmp.put("pos", pos);
            return hmBmp;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(HashMap<String, Object> result) {
        // this is the img path that leads to a local image that was just
        // saved on the phone.
        String imgPath = (String) result.get("blank_start");
        // the position of the image in the listview
        int position = (Integer) result.get("pos");
        // local adapter
        SimpleAdapter adapter = (SimpleAdapter) getListAdapter();
        // hashmap entry from the local adapter at the position of the image
        // that we just loaded.
        HashMap<String, Object> hm = (HashMap<String, Object>) adapter
                .getItem(position);
        // replace the actual blank image with the image path that we just
        // loaded
        hm.put("blank_start", imgPath);
        // update listview
        adapter.notifyDataSetChanged();
        // we are done with the current position increment position and move
        // on.
        position++;
        // this while loop finds the next position in the adapter that does
        // not have false for an image path. False indicates that there is
        // no image and i should load a default image.
        while (position < adapter.getCount()) {
            hm = (HashMap<String, Object>) adapter.getItem(position);
            imgPath = (String) hm.get("image");

            if (!imgPath.equalsIgnoreCase("false")) {
                break;
            }
            position++;
        }

        // checks to make sure that the position is not out of bounds on the
        // adapter. If in bounds then there might be more images to load.
        // Start a new ImageLoader. This is a recursive Class.
        if (position < adapter.getCount()) {
            ImageLoaderTask imageLoader = new ImageLoaderTask();

            hm.put("pos", (position));
            imageLoader.execute(hm);
        }

    }
当暂停/删除调用片段时,异步任务会发生什么情况?我假设任务完成了,但如果有人能证实这一点,那就太好了

这是不正确的;框架不会通过取消您在后台线程中所做的工作来为您完成工作。调用诸如
onPause()
onResume()
之类的回调的原因是通知您的应用程序,您需要清理并取消任何不在像
服务这样的长寿命组件中的正在运行的工作

在这种情况下,如果不取消,任务将继续运行。由于该类被定义为非静态内部类,这也意味着您创建了临时内存泄漏,因为
AsyncTask
包含对
片段的隐式引用,并且由于任务附加到正在运行的线程,因此即使在
onDestroy()之后,也无法对对象(或其成员)进行垃圾收集


您需要执行
AsyncTask
,这样它会检查取消标志,您可以从
onPause()
或类似的回调手动取消工作。

我认为您在这方面做得对

在编写自定义
AsyncTask
s时,许多开发人员忘记了处理任务取消的必要性。简单地取消任务并不意味着它的代码不会在(例如)
活动
/
片段
资源上执行,这些资源可能在当时被释放。这通常通过以下步骤完成:

  • 创建任务后,保存对该任务的引用
  • 活动
    /
    片段
    完成后取消所有正在运行的任务。这通常是在
    Activity.onDestroy()
    /
    Fragment.onDestroy()
    中完成的。删除对已取消任务的所有引用
  • 在任务代码中:
  • doInBackground()
    中定期检查它是否已取消()。如果是,请清理并中止进一步执行
  • 最终在
    onCancelled()
    (在UI线程上运行)中处理取消
  • onPostExecute()
    中执行已取消任务的任何处理(如果任务已取消,则执行该操作时会产生
    null
    结果)

  • 272是哪条线?很可能您正在尝试引用不再存在的内容,因为活动已完成()第272行是
    String imgPath=(String)result.get(“blank_start”)超出onPostExecute。这是在引用图像加载器类内部的内容,因为它是从DoIn后台传递的。您应该首先检查result.hasKey(“blank_start”)。看起来该键没有项,因此返回null。我不认为该键缺少项,因为只有在异步任务完成加载之前取消异步任务时才会发生错误。因此,第3条在
    onPostExecute()中解释了null结果
    因为当我按下后退按钮时,碎片会被移除。我没有使用显示/隐藏,因为我有太多的问题,我无法跟踪。这是完美的。确切地说,我所需要的信息是以一种对我所处理的事情有意义的方式来解释的。谢谢你,安德烈。我要去实现了。没错,但是如果一个任务在片段/活动被销毁后执行,那么NPE或其他错误可能会有更多的原因。只是要小心:)哦,记住,您仍然可以在
    onPostExecute()
    (例如)中添加断点,并在
    变量
    选项卡中查看变量值。这有时很有帮助。
    01-14 20:09:28.752: E/AndroidRuntime(6069): FATAL EXCEPTION: main
    01-14 20:09:28.752: E/AndroidRuntime(6069): java.lang.NullPointerException
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at com.appdomum.doublea.ListFrag$ImageLoaderTask.onPostExecute(ListFrag.java:272)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at com.appdomum.doublea.ListFrag$ImageLoaderTask.onPostExecute(ListFrag.java:1)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.os.AsyncTask.finish(AsyncTask.java:417)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.os.AsyncTask.access$300(AsyncTask.java:127)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.os.Handler.dispatchMessage(Handler.java:99)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.os.Looper.loop(Looper.java:130)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at android.app.ActivityThread.main(ActivityThread.java:3806)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at java.lang.reflect.Method.invokeNative(Native Method)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at java.lang.reflect.Method.invoke(Method.java:507)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at     com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
    01-14 20:09:28.752: E/AndroidRuntime(6069):     at dalvik.system.NativeStart.main(Native Method)