我正在开发一个应用程序,在执行的某个部分中,用户将能够以图形形式查看文本文件中的数据。但是,由于文本文件可以有几列(并且打算为每列创建一个图形),因此仅使用UI线程可能会阻塞应用程序一段时间。所以我的问题是:Android上是否有任何类可以让我并行创建这些图(View
s,并在所有图准备好后将它们添加到父级布局中?
我的第一个想法是按如下方式使用ExecutorService
(为简单起见,使用TextView
而不是GraphView
是我正在使用的库中的类项目):
createTextsInParallel
实现:public void createTextsInParallel(){
ExecutorService executor = (ExecutorService) Executors.newFixedThreadPool(3);
List<TextBuilderTask> taskList = new ArrayList<>();
for (int i = 0; i < arrays.size(); i++){ // arrays is an ArrayList<ArrayList<Double>>
if (arrays.get(i) == null) continue;
taskList.add(new TextBuilderTask(this, arrays.get(i), i));
}
List<Future<TextView>> futureList = null;
try {
futureList = executor.invokeAll(taskList);
} catch (InterruptedException e){
e.printStackTrace();
}
executor.shutdown();
if (futureList != null){
for (int i = 0; i < futureList.size(); i++){
TextView tv = futureList.get(i).get();
parentLayout.addView(tv); // parentLayout is a LinearLayout
}
}
}
TextBuilderTask
实现:class TextBuilderTask implements Callable<TextView> {
protected MyActivity activity;
protected ArrayList<Double> array;
protected int pos;
public TextBuilderTask(MyActivity activity, ArrayList<Double> array, int pos){
this.activity = activity;
this.array = array;
this.pos = pos;
}
@Override
public TextView call() throws Exception {
TextView tv = new TextView(this.activity);
tv.setText(String.format("%d: %s", this.pos, Arrays.toString(this.array)));
return tv;
}
}
但是上面的方法抛出以下异常:
Caused by: java.lang.RuntimeException: Can't create handler inside thread Thread[pool-1-thread-1,5,main] that has not called Looper.prepare()
那我应该在哪里打电话Looper.prepare()
?基于先前的SO问题,每当我致电Looper.prepare()
时,我也应同时致电Looper.loop()
和Looper.quit()
。但是由于我使用ExecutorService
来完成这项工作,所以我不确定应该在哪里给他们打电话。任何帮助表示赞赏。
答案 0 :(得分:1)
我无法运行您的代码,因为它包含一些错误并且无法立即编译,但是我怀疑问题出在以下事实:您在辅助线程中实例化了视图(即调用{ {1}})。
我知道这正是您的目标,但这可能不是一个好主意,因为它取决于您要实例化的View的实现。例如,如果其构造函数创建了一些处理程序,则将需要准备循环程序。
您可以尝试使用call()
方法来执行此操作,但是仍然存在一个事实,那就是此时,其处理程序可能正在意外线程上运行。
它似乎也是特定于平台的,因此它可能在某些手机上运行而不在其他手机上运行,具体取决于该特定View的实际实现。我建议在这里看看这篇文章,也许您可以尝试遵循其中一些建议(例如,使用AsyncLayoutInflater): Inflate a view in a background thread