【问题标题】:How to load imageViews in AsyncTask如何在 AsyncTask 中加载 imageViews
【发布时间】:2016-11-15 02:37:37
【问题描述】:

我的应用中有 ViewPager,它包含 7 个片段,每个片段包含多个图像。 我想在每个片段加载它的图像时显示 ProgressBar。 所以我创建了在后台加载图像的 AsyncTask。 问题是我无法使用 Picasso 库加载图像,它显示了一些错误。 有人可以帮我弄清楚怎么做吗?

编辑:我问这个的原因是因为用毕加索加载所有图像大约需要 1.5 秒,而且看起来很滞后。使用“android:src”时,应用程序有时会崩溃,因为 OutOfMemory 问题,“应用程序可能在其主线程上做了太多工作。”所以我正在寻找更好的方法。

谢谢!!!

fragment1.java:

public class Fragment1 extends Fragment {

public Fragment1() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
                         Bundle savedInstanceState) {

     View rootView = inflater.inflate(R.layout.fragment_frag1, container, false);

    LoadImagesTask loadImagesTask = new LoadImagesTask();
    loadImagesTask.execute();

                // Inflate the layout for this fragment
        return rootView;
}

private class LoadImagesTask extends AsyncTask<Void, Void, Void> {
        ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.loading);
        ImageView image1 = (ImageView) getActivity().findViewById(R.id.imageView_S0P1);
        ImageView image2 = (ImageView) getActivity().findViewById(R.id.imageView_S0P2);
        ImageView image3 = (ImageView) getActivity().findViewById(R.id.imageView_S0P3);
        ImageView image4 = (ImageView) getActivity().findViewById(R.id.imageView_S0P4);
        ImageView image5 = (ImageView) getActivity().findViewById(R.id.imageView_S0P5);
        ImageView image6 = (ImageView) getActivity().findViewById(R.id.imageView_S0P6);
        ImageView image7 = (ImageView) getActivity().findViewById(R.id.imageView_S0P7);
        ImageView image8 = (ImageView) getActivity().findViewById(R.id.imageView_S0P8);
        ImageView image9 = (ImageView) getActivity().findViewById(R.id.imageView_S0P9);
        ImageView image10 = (ImageView) getActivity().findViewById(R.id.imageView_S0P10);

    @Override
    protected Void doInBackground(Void... params) {

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Picasso.with(getActivity()).load(R.drawable.s0p1).into(image1);
                Picasso.with(getActivity()).load(R.drawable.s0p2).into(image2);
                Picasso.with(getActivity()).load(R.drawable.s0p3).into(image3);
                Picasso.with(getActivity()).load(R.drawable.s0p4).into(image4);
                Picasso.with(getActivity()).load(R.drawable.s0p5).into(image5);
                Picasso.with(getActivity()).load(R.drawable.s0p6).into(image6);
                Picasso.with(getActivity()).load(R.drawable.s0p7).into(image7);
                Picasso.with(getActivity()).load(R.drawable.s0p8).into(image8);
                Picasso.with(getActivity()).load(R.drawable.s0p9).into(image9);
                Picasso.with(getActivity()).load(R.drawable.s0p10).into(image10);
            }
        });

        return null;
    }

    @Override
    protected void onPostExecute(Void event) {
        progressBar.setVisibility(View.GONE);
    }
}
}

Logcat:

07-12 17:03:32.838 17497-17581/appinventor.ai_itiel_maimon.Rubiks_cube E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
                                                                                     Process: appinventor.ai_itiel_maimon.Rubiks_cube, PID: 17497
                                                                                     java.lang.RuntimeException: An error occurred while executing doInBackground()
                                                                                         at android.os.AsyncTask$3.done(AsyncTask.java:309)
                                                                                         at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                                                                                         at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                                                                                         at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                                                                                         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
                                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                                         at java.lang.Thread.run(Thread.java:818)
                                                                                      Caused by: java.lang.IllegalStateException: Method call should happen from the main thread.
                                                                                         at com.squareup.picasso.Utils.checkMain(Utils.java:136)
                                                                                         at com.squareup.picasso.RequestCreator.into(RequestCreator.java:615)
                                                                                         at com.squareup.picasso.RequestCreator.into(RequestCreator.java:601)
                                                                                         at appinventor.ai_itiel_maimon.Rubiks_cube.Intro$LoadImagesTask.doInBackground(Intro.java:68)
                                                                                         at appinventor.ai_itiel_maimon.Rubiks_cube.Intro$LoadImagesTask.doInBackground(Intro.java:36)
                                                                                         at android.os.AsyncTask$2.call(AsyncTask.java:295)
                                                                                         at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                                         at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) 
                                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
                                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                                                         at java.lang.Thread.run(Thread.java:818) 

【问题讨论】:

  • 你不需要异步任务。这些图像是本地的,您可以直接从主线程调用 Picaso..load(img).into(img)。
  • @FishStix 我知道,但是加载所有图像大约需要 1.5 秒,而且看起来很滞后
  • 从网络下载资产总是需要时间。如果您的资产是本地的,看起来可能是 R.drawable.s0p1,为什么不能在布局 xml 中设置“src”属性?通过 URL 下载图像通常需要 1.5 秒,因此应使用加载器和淡入等工具。
  • @FishStix 你基本上是对的,但在我的情况下,应用程序崩溃是因为 OutOfMemory 问题
  • 这些图片有多大?不管批评你的代码......可能还有其他问题在起作用。

标签: java android android-fragments android-asynctask progress-bar


【解决方案1】:

AsyncTask 背后的想法是 doInBackground 做后台工作,然后你可以返回一些将作为参数传递给在主线程中执行的 onPostExecute 的东西。 所以尝试从 onPostExecute() 方法设置图像:) 但是你可以在不使用 AsyncTask 的情况下轻松做到这一点,只需这样做:

public class BlankFragment extends Fragment {


    private ImageView imv1;
    private ImageView imv2;
    private ImageView imv3;
    private ImageView imv4;
    private ImageView imv5;
    private ImageView imv6;
    private ImageView imv7;
    private ImageView imv8;
    private ImageView imv9;
    ProgressDialog progressDialog = null;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_blank, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        imv1 = (ImageView) getActivity().findViewById(R.id.imageView);
        imv2 = (ImageView) getActivity().findViewById(R.id.imageView2);
        imv3 = (ImageView) getActivity().findViewById(R.id.imageView3);
        imv4 = (ImageView) getActivity().findViewById(R.id.imageView4);
        imv5 = (ImageView) getActivity().findViewById(R.id.imageView5);
        imv6 = (ImageView) getActivity().findViewById(R.id.imageView6);
        imv7 = (ImageView) getActivity().findViewById(R.id.imageView7);
        imv8 = (ImageView) getActivity().findViewById(R.id.imageView8);
        imv9 = (ImageView) getActivity().findViewById(R.id.imageView9);
    }

    private void setImage() {
        // show progress dialog
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // set your images here.
            }
        });
        // dismiss progressDialog here
    }
}

【讨论】:

  • AsyncTask 通常用于需要很长时间才能完成的网络或进程。我认为在这种情况下您不需要使用 AsyncTask。 :) 只需编写一个方法并调用它。
  • 我用这个是因为加载所有图片大约需要 1.5 秒,而且看起来很卡
  • 你知道另一种实现我想要的方法吗?
  • 您可以尝试使用处理程序 :) vogella.com/tutorials/AndroidBackgroundProcessing/article.html 在处理图像时向用户显示进度对话框将使您的应用程序更流畅
  • 只需编辑我的答案。上面是一个简单的方法(就像你所做的那样),只需使用一个带有进度对话框的简单线程,然后在 onActivityCreated() 或任何你想要的地方调用该方法。
【解决方案2】:

如果你想得到一个好的答案,你应该在这里发布更多代码。
一般来说,您可以简单地将可绘制对象用作 ImageView xml 实体中的“android:src”(您在此处所做的几乎相同,仅使用此处的编程方法...) 或者在 Main\UI 线程上使用 Picasso(它与唯一负责渲染 UI 组件的线程同名),即在 inflate 方法上。


一般来说,尝试并查看更多关于“如何”使用片段和通用 android 设计模式的教程,您显然仍在学习,但使用谷歌推荐的方法将简化您的学习并最大限度地减少错误。

【讨论】:

  • 我不是初学者。我知道如何执行您提到的操作,但是使用毕加索加载所有图像大约需要 1.5 秒,而且看起来非常滞后。使用“android:src”应用程序有时会崩溃,因为 OutOfMemory 问题,“应用程序可能在其主线程上做太多工作。”所以我正在寻找更好的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 2020-08-17
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多