【问题标题】:Android: Loading bitmap to dynamic viewAndroid:将位图加载到动态视图
【发布时间】:2014-01-10 01:31:56
【问题描述】:

我对 Android 比较陌生,并且正在开发一个应用程序,该应用程序会将位图加载到使用 ImageView 动态创建的布局中。布局和 ImageView 的数量基于一些动态数据(即 API 调用)。我想在动态创建位图并将它们添加到主布局后将它们加载到这些 ImageView 中。由于我将创建多个动态布局并加载多个位图,因此无法在主线程上同步完成。我目前正在使用基于 AsyncTasks 的解决方案,但我认为可能有更有效的方法(可能使用 Handler/Runnable)。

目前,我已经通过以下方式实现了一个使用 AsyncTasks 的解决方案:

1) 从主线程启动第一个 AsyncTask

for(Event event : events.getEventList()) {
  // Create an UpdateCalendarUITask to update the UI
  CalendarUpdateTask calendarTask = new CalendarUpdateTask(this, parentView);
  calendarTask.execute(event);
}

2)创建并填充布局(添加Text和Image视图),将新创建的动态视图添加到布局中,并在完成时回调主线程(使用接口)。

public class CalendarUpdateTask extends AsyncTask<Event, Void, RelativeLayout> {

  private final WeakReference<Activity> activityReference;
  private final WeakReference<ViewGroup> parentViewReference;
  ....
  public CalendarUpdateTask(Context context, ViewGroup parentView) {
    parentViewReference = new WeakReference<ViewGroup>(parentView);
    activityReference = new WeakReference<Activity>((Activity) context);
  }

  @Override
  protected RelativeLayout doInBackground(Event... params) {
    myEvent = params[0];
    return updateGameView(myEvent); // returns created RelativeLayout
  }

  @Override
  protected void onPostExecute(RelativeLayout result) {
    super.onPostExecute(result);
    // Add the Game/Event view to the Events View
    if( // Reference and nulls checks ) {
        ViewGroup parentView = parentViewReference.get();            
        parentView.addView(result);
        TaskListener listener = (TaskListener) activityReference.get();
        listener.loadImages(myEvent);
    }
  }
  ....    
}

3) 监听函数 loadImages(...) 启动另一个 AsyncTask 来加载位图(类似于this

这工作正常。但是,加载大量图像仍然有点慢,因为直到创建视图之后才加载位图。我之前不能调用它,因为在创建 ImageView 之前我没有对它的引用。我无法从 CalendarUpdateTask 启动第二个 AsyncTask,因为它必须始终从主线程启动。

理想情况下,我希望同时启动这两个操作,并在两个操作完成后通知回调,以便将位图加载到新的 ImageView 中。

必须有更好的选择对吗?提前致谢。

【问题讨论】:

    标签: java android multithreading bitmap android-asynctask


    【解决方案1】:

    您应该使用ListViewGridViewAdapter 之类的东西来跟踪您的数据对象。这些内置类会自动管理可见和不可见的内容,并会在需要时要求您提供视图。那是您应该创建 ImageView 实例的时候。加载图像是另一个需要小心的故事,因为在开始加载图像和完成图像之间,保持视图可能会被破坏。

    【讨论】:

    • 是的,我研究过 ListView,我认为这是另一种可能的解决方案。我想我需要一个带有自定义对象的 ListView,因为我实际上是将一堆 RelativeLayouts(具有多个 Text 和 Image 视图)插入到 ScrollView 中。你碰巧有一个如何做到这一点的例子吗?
    • 对不起,我没有现成的例子可以分享。使用 XML 布局和适配器,可能是加载器来获取图像本身。寻找一些关于 Adapter 或其他资源的 GoogleIO 演讲,那里有很多。
    • 在使用 ListView 对每个“项目”视图进行自定义布局后,我正在使用它。感谢您的帮助。
    【解决方案2】:

    如果您只需要将图像从服务器加载到特定视图,则可以使用不同的库来执行此操作:

    1. 通用图片加载器。
    2. Google Volley

    这些库将询问将加载此位图的 URL 和视图,并且它们还在图像加载的不同点提供侦听器。 这些库还可以将它们缓存在磁盘上,这样应用程序就不会一次又一次地获取它们。并将创建一个 Hashmap,其中 key 作为图像的 URL,Value 作为 Bitmap。

    以我的方式,对于这种特殊情况,使用 AsyncTask 并不是一个好方法,因为即使它们在后台线程上运行,但多个 AsyncTask 将一个接一个地运行,即同步运行。

    因此,如果您只想加载图像,这将是一个好方法。

    如果您有任何疑问,请随时提出。

    【讨论】:

    • 我正在加载的图像实际上存储在我的可绘制文件夹中,但直到连接到服务器后我才知道要加载哪些图像。我不确定这些库是否矫枉过正。 AsyncTask 可以与 executeOnExecutor 和 ThreadPoolExecutor 并行运行吗?
    • 是的,您可以使用 ThreadPoolExecutor 调整 AsyncTasks 的执行方式。
    猜你喜欢
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多