安卓:异步任务线程睡眠错误



在StackOverflow的职业生涯中有一个问题。我希望你能帮助我。

发生了什么:

我有一个片段,我想设置一些带有一些

日期的回收器视图,它一直有效,直到我想用一些 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();
    }
}



最后一种方法是填充FromJson:

 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:只有创建视图层次结构的原始线程才能触及其视图。
我知道错误的主要部分在这里:
添加睡眠后出错

@Override
    protected Void doInBackground(Void... voids) {
        try {
            Thread.sleep(2200); 
            populateFromJson();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

populateFromJson()尝试使用recicleView。视图(和视图子类)对象不能从除活动线程之外的任何线程使用。

当您在 AsyncTask onPreExecute上执行.execute()时,onPostExecute将由活动线程执行,并由子线程doInBackground

一旦你得到这个,你很容易理解,为了避免这个错误,你应该在onPostExecute中调用populateFromJson()

注意:如果你的doInBackground方法真的需要等待,那么有更有效的方法可以做到这一点。 看看这里和这里

不,错误的根本原因是您正在尝试使用工作线程中的视图。应该在此方法中获取调用的结果

@Override
protected void onPostExecute(Void result) {
  //work with you RecyclerView here
}

不要使用 AsyncTask。只需在onCreateView()中调用populateFromJson()即可。

您无法从后台线程更新视图,让您的异步任务在doInBackground中返回项目列表,onPostExecute将接收列表作为参数,并且您可以从该方法更新回收器视图。

一种更简单的方法是用 rxjava 替换异步任务

相关内容

最新更新