I'm developing an application where, in a certain part of its execution, the user will be able to see the data in a text file in the form of a graph. However, as the text file can have several columns (and it's intended to create a graph for each column), using only the UI thread can block the application for a few moments. So my question is: is there any class on Android that allows me to create these graphs (View
s) in parallel and, when all the graphs are ready, add them to the parent layout?
My first thought was to use an ExecutorService
as follows (for the sake of simplicity, using a TextView
instead of GraphView
, class from a library that I'm using in my project):
createTextsInParallel
implementation:
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
implementation:
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;
}
}
But the above throws the following exception:
Caused by: java.lang.RuntimeException: Can't create handler inside thread Thread[pool-1-thread-1,5,main] that has not called Looper.prepare()
So where should I call Looper.prepare()
? Based on previous SO questions, whenever I call Looper.prepare()
, I should call Looper.loop()
and Looper.quit()
somewhere too. But since I'm using a ExecutorService
to do the job, I'm not sure where should I call them. Any help is appreciated.