0

I've read a lot of questions on AsyncTask problems of different kinds, but I seem not to find the problem I'm facing.

Android Studio insists on making my custom AsyncTask static with the following note:

This AsyncTask class should be static or leaks might occur

For that reason I've been trying on using WeakReference to the Activity the task runs in. Problem is that I want to use findViewById() in onPre and onPostExecute and I cannot to access the method. I've found that:

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

does not produce an error in Android Studio, but it crashes the app.

How to solve the problem of not accessing findViewById() in the custom static AsyncTask?

Code generally works if I get rid of weakReference and make AsyncTask it non-static

Here's my AsyncTask: (the empty while loop is there on purpose so it waits until the global variable has some data.

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);
    }
}

And that's how I am calling it:

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

EDIT:

I've tried with creating a separate file with the LoadingDictionaryAsync where static is not a problem anymore, but I still have problem with passing MainScreenActivity it, so findViewById() cannot be used.

What is the proper way of passing Activity? I want to pass it in onNavigationItemSelected() and onQueryTextChange() in SearchView?

devaga
  • 326
  • 2
  • 15

2 Answers2

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

Demo: Details in my class:

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);
    }
}

And Call AsyncTask in MainActivity with context is 'this' keyword:

String URL="url";
new ParseUrl(this).execute(URL);
O Thạnh Ldt
  • 1,103
  • 10
  • 11
0

I've fixed the problem in the following way:

  1. Moved Async classes I've created to separate files.
  2. Switched the use of WeakReference to Context
  3. Preceded findViewById() with ((MainScreenActivity)context).
  4. Called the AsyncTasks with MainScreenActivity.this

So the call is:

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

And now the AsyncTask class looks like the following:

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);
}
}
devaga
  • 326
  • 2
  • 15