Я изучаю ThreadPoolExecutor, следуя этому учебнику . Чтобы продемонстрировать его использование, я сделал простой проект android, он имеет обзор переработчика, который покажет некоторые строки. Первоначально массив строк (String[] myDataset = new String[10]
) имеет 10 нулей. Мой threadPoolExecutor генерирует несколько случайных строк и заполняет массив. Поэтому, всякий раз, когда новая строка генерируется и помещается в массив, я должен вызывать notifyDataSetChanged()
, чтобы recyclerView обновлял и отображал эти случайные строки.
проблема
Я не понимаю, как позвонить notifyDataSetChanged()
, и поэтому меня приковали. Я получил это исключение:
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Поскольку я знаю AsyncTask, я понимаю, что эта ошибка означает, что я не могу вызвать этот метод в фоновом потоке, но я должен вызывать его в основном потоке / потоке пользовательского интерфейса (так в AsyncTask, это будет выглядеть так:
@Override
protected void onPostExecute(String result) {
weakReference.get().notifyDataSetChanged(); // something like that
}
). Мне нужен его аналог ThreadPoolExecutor. Я сделал Google и нашел это , но я не уверен, как это сделать.
Необходимый сегмент кода приведен ниже:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] myDataset;
private final ThreadPoolExecutor threadPoolExecutor;
private Future future;
private Runnable getRunnable(final int i) {
Runnable runnable = new Runnable() {
@Override
public void run() {
String randomString = MyAdapter.getRandomString(i)+" "+i; // <--create random string
Log.e(TAG, randomString);
myDataset[i] = randomString;
try { Thread.sleep(3000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
};
return runnable;
}
public void doSomeBackgroundWork(){
Runnable[] commands = new Runnable[myDataset.length];
for(int i1=0; i1<commands.length; i1++) {
final int j1 = i1;
commands[j1] = () -> {
String randomString = MyAdapter.getRandomString(j1)+" "+j1;
Log.e(TAG, randomString);
myDataset[j1] = randomString;
try { Thread.sleep(3000); }
catch (InterruptedException e) { e.printStackTrace(); }
// notifyDataSetChanged(); // <-------- Error. Where/How should I call it?
};
threadPoolExecutor.execute(commands[j1]);
}
}
public MyAdapter(String[] myDataset) {
this.myDataset = myDataset; // {null, null, ... ...}
this.threadPoolExecutor = DefaultExecutorSupplier.getInstance().forBackgroundTasks(); // returns new ThreadPoolExecutor( ... parameters... );
// future[i] = threadPoolExecutor.submit(command); future[i].cancel(true); use it like this
doSomeBackgroundWork();
}
// ... the rest of the recyclerview related code
}
Может ли кто-нибудь мне помочь? Спасибо за чтение.