Android: 异步任务线程休眠错误
Android: Async Task Thread Sleep Error
我在 Whosebug 的职业生涯中遇到了第一个问题。我希望你能帮助我。
发生了什么:
我有片段,我想在其中设置一些带有一些日期的 recyclerView,它一直有效,直到我想用一些 ErrorMgs 做 ProgressDialog。
这是我的 onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recycler_view, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.my_recycler_view);
textViewErrorMsg = (TextView) view.findViewById(R.id.tv_error_message);
progressBarLoading = (ProgressBar) view.findViewById(R.id.pb_loading);
new TakeDates().execute();
return view;
}
我添加 AsyncTask:
@SuppressLint("StaticFieldLeak")
class TakeDates extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(getActivity());
progressDialog.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
progressDialog.setMessage("Loading places...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(2200);
populateFromJson();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (progressDialog.isShowing())
progressDialog.dismiss();
}
}
最后一个方法是 populateFromJson:
private void populateFromJson() {
ConnectivityManager conMgr = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
assert conMgr != null;
NetworkInfo i = conMgr.getActiveNetworkInfo();
if (i != null && i.isConnected() && i.isAvailable()) {
ApiService api = RetroClient.getApiService(PLACES_URL);
Call<PlaceList> call = api.getMyJSON();
call.enqueue(new Callback<PlaceList>() {
@Override
public void onResponse(Call<PlaceList> call, Response<PlaceList> response) {
if (response.isSuccessful()) {
itemList = response.body().getItemList();
adapter = new RecyclerViewPlaceAdapter(itemList, getContext());
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
showPlaces();
} else {
showErrorMessage("Try to restart your app.");
}
}
@Override
public void onFailure(Call<PlaceList> call, Throwable t) {
showErrorMessage("Here is the main error: " + t.getMessage() + "\nTry to restart your app.");
}
});
} else {
showErrorMessage("Internet Connection Not Available" + "\nTry to find better connection to the internet.");
}
}
现在关于错误:
1) 原因:android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及它的视图。
我知道错误的主要部分在这里:
添加后 SLEEP Make ERROR
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(2200);
populateFromJson();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
不,错误的根本原因是您正在尝试使用来自工作线程的视图。
应该在这个方法中得到你的调用结果
@Override
protected void onPostExecute(Void result) {
//work with you RecyclerView here
}
不要使用 AsyncTask。只需在 onCreateView() 中调用 populateFromJson()
。
populateFromJson()
尝试使用 recicleView
。 View(和 View 子类)对象不能从除 Activity 线程之外的任何线程使用。
当您在 AsyncTask 上执行 .execute()
时,onPreExecute
和 onPostExecute
将由 activity 线程执行,而 doInBackground
将由子线程执行。
一旦你明白了这一点,你就会很容易理解,为了避免这个错误,你应该在 onPostExecute
中调用 populateFromJson()
N.B。如果您的 doInBackground 方法真的需要等待,那么有更有效的方法可以做到这一点。看看here and here
你不能从后台线程更新视图,让你的异步任务 return doInBackground 中的项目列表,onPostExecuted 将接收列表作为参数,你可以从该方法更新回收器视图.
一个更简单的方法是用 rxjava 替换异步任务
我在 Whosebug 的职业生涯中遇到了第一个问题。我希望你能帮助我。
发生了什么:
我有片段,我想在其中设置一些带有一些日期的 recyclerView,它一直有效,直到我想用一些 ErrorMgs 做 ProgressDialog。
这是我的 onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.recycler_view, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.my_recycler_view);
textViewErrorMsg = (TextView) view.findViewById(R.id.tv_error_message);
progressBarLoading = (ProgressBar) view.findViewById(R.id.pb_loading);
new TakeDates().execute();
return view;
}
我添加 AsyncTask:
@SuppressLint("StaticFieldLeak")
class TakeDates extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(getActivity());
progressDialog.getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
progressDialog.setMessage("Loading places...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
}
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(2200);
populateFromJson();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (progressDialog.isShowing())
progressDialog.dismiss();
}
}
最后一个方法是 populateFromJson:
private void populateFromJson() {
ConnectivityManager conMgr = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
assert conMgr != null;
NetworkInfo i = conMgr.getActiveNetworkInfo();
if (i != null && i.isConnected() && i.isAvailable()) {
ApiService api = RetroClient.getApiService(PLACES_URL);
Call<PlaceList> call = api.getMyJSON();
call.enqueue(new Callback<PlaceList>() {
@Override
public void onResponse(Call<PlaceList> call, Response<PlaceList> response) {
if (response.isSuccessful()) {
itemList = response.body().getItemList();
adapter = new RecyclerViewPlaceAdapter(itemList, getContext());
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
showPlaces();
} else {
showErrorMessage("Try to restart your app.");
}
}
@Override
public void onFailure(Call<PlaceList> call, Throwable t) {
showErrorMessage("Here is the main error: " + t.getMessage() + "\nTry to restart your app.");
}
});
} else {
showErrorMessage("Internet Connection Not Available" + "\nTry to find better connection to the internet.");
}
}
现在关于错误:
1) 原因:android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及它的视图。
我知道错误的主要部分在这里:
添加后 SLEEP Make ERROR
@Override
protected Void doInBackground(Void... voids) {
try {
Thread.sleep(2200);
populateFromJson();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
不,错误的根本原因是您正在尝试使用来自工作线程的视图。 应该在这个方法中得到你的调用结果
@Override
protected void onPostExecute(Void result) {
//work with you RecyclerView here
}
不要使用 AsyncTask。只需在 onCreateView() 中调用 populateFromJson()
。
populateFromJson()
尝试使用 recicleView
。 View(和 View 子类)对象不能从除 Activity 线程之外的任何线程使用。
当您在 AsyncTask 上执行 .execute()
时,onPreExecute
和 onPostExecute
将由 activity 线程执行,而 doInBackground
将由子线程执行。
一旦你明白了这一点,你就会很容易理解,为了避免这个错误,你应该在 onPostExecute
populateFromJson()
N.B。如果您的 doInBackground 方法真的需要等待,那么有更有效的方法可以做到这一点。看看here and here
你不能从后台线程更新视图,让你的异步任务 return doInBackground 中的项目列表,onPostExecuted 将接收列表作为参数,你可以从该方法更新回收器视图.
一个更简单的方法是用 rxjava 替换异步任务