静态AsyncTask和findViewById()

时间:2017-11-15 12:32:49

标签: java android android-asynctask static findviewbyid

我已经阅读了很多关于不同类型的AsyncTask问题的问题,但我似乎没有找到我面临的问题。

Android Studio坚持使用以下注释使我的自定义AsyncTask静态:

  

此AsyncTask类应该是静态的,否则可能会发生泄漏

出于这个原因,我一直在尝试将WeakReference用于任务运行的Activity。问题是我想在onPre和onPostExecute中使用findViewById()而我无法访问该方法。 我发现了:

weakReference.get().findViewById(R.id.dictionaryLoading).setVisibility(View.VISIBLE);

在Android Studio中不会产生错误,但会导致应用崩溃。

如何解决在自定义静态AsyncTask中不访问findViewById()的问题?

代码通常可以正常工作,如果我摆脱weakReference并使AsyncTask成为非静态

这是我的AsyncTask :(空的while循环是有目的的,所以等到全局变量有一些数据。

public static class LoadingDictionaryAsync extends AsyncTask<Void, Void, Void> {

    private final WeakReference<MainScreenActivity> weakReference;

    private LoadingDictionaryAsync(MainScreenActivity mainScreenActivity){
        this.weakReference = new WeakReference<>(mainScreenActivity);
    }


    @Override
    protected void onPreExecute() {
        weakReference.get().findViewById(R.id.dictionaryLoading).setVisibility(View.VISIBLE);
        weakReference.get().findViewById(R.id.dictionaryListView).setVisibility(View.GONE);
    }

    @Override
    protected Void doInBackground(Void... voids) {

        if (vocabulariesGlobal == null || vocabulariesGlobal.size() == 0) {
            weakReference.get().loadDatabaseVocabularyToDictionary();
        }

        while (vocabulariesGlobal == null || vocabulariesGlobal.size() == 0) {
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        weakReference.get().loadDictionaryOnTheList(vocabulariesGlobal);
        weakReference.get().findViewById(R.id.dictionaryLoading).setVisibility(View.GONE);
        weakReference.get().findViewById(R.id.dictionaryListView).setVisibility(View.VISIBLE);
    }
}

这就是我的称呼方式:

LoadingDictionaryAsync loadingDictionaryAsync = new LoadingDictionaryAsync((MainScreenActivity)getParent());
loadingDictionaryAsync.execute();

编辑:

我尝试使用 LoadingDictionaryAsync 创建一个单独的文件,其中静态不再是问题,但我仍然有传递MainScreenActivity的问题,所以 findViewById()不能使用。

传递Activity的正确方法是什么?我想在SearchView中的 onNavigationItemSelected() onQueryTextChange()中传递它?

2 个答案:

答案 0 :(得分:0)

我已按以下方式解决了问题:

  1. 移动了我创建的异步类以分隔文件。
  2. 将WeakReference的使用转换为上下文
  3. ((MainScreenActivity)context).
  4. 之前使用findViewById()
  5. 使用MainScreenActivity.this
  6. 调用AsyncTasks

    所以电话是:

    LoadingDictionaryAsync loadingDictionaryAsync = new LoadingDictionaryAsync(MainScreenActivity.this);
    loadingDictionaryAsync.execute();
    

    现在,AsyncTask类如下所示:

    public class LoadingDictionaryAsync extends AsyncTask<Void, Void, Void> {
    
    
    private Context context;
        public LoadingDictionaryAsync(Context context) {
            this.context = context;
        }
    
    @Override
    protected void onPreExecute() {
    
        ((MainScreenActivity)context).findViewById(R.id.dictionaryLoading).setVisibility(View.VISIBLE);
        ((MainScreenActivity)context).findViewById(R.id.dictionaryListView).setVisibility(View.GONE);
    }
    
    @Override
    protected Void doInBackground(Void... voids) {
    
    
        if (((MainScreenActivity)context).vocabulariesGlobal == null || ((MainScreenActivity)context).vocabulariesGlobal.size() == 0) {
            ((MainScreenActivity)context).loadDatabaseVocabularyToDictionary();
        }
        while (((MainScreenActivity)context).vocabulariesGlobal == null || ((MainScreenActivity)context).vocabulariesGlobal.size() == 0) {
        }
        return null;
    }
    
    @Override
    protected void onPostExecute(Void aVoid) {
    
        ((MainScreenActivity)context).loadDictionaryOnTheList(((MainScreenActivity)context).vocabulariesGlobal);
        ((MainScreenActivity)context).findViewById(R.id.dictionaryLoading).setVisibility(View.GONE);
        ((MainScreenActivity)context).findViewById(R.id.dictionaryListView).setVisibility(View.VISIBLE);
    }
    }
    

答案 1 :(得分:0)

Context mContext;
//IN onPostExecute(String s)
TextView tv =((Activity)mContext).findViewById(R.id.tvData);

演示:我班上的详细信息:

public class ParseUrl extends AsyncTask<String, Void, String> {

    Context mContext;

    public ParseUrl(Context context) {
        mContext = context;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        //showProgessDialog();
    }

    @Override
    protected String doInBackground(String... params) {
        String s = "";
        return s;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        TextView tv = ((Activity) mContext).findViewById(R.id.tvData);
        tv.setText(s);
    }
}

使用上下文调用MainActivity中的AsyncTask是'this'关键字:

String URL="url";
new ParseUrl(this).execute(URL);