Update UI from an AsyncTaskLoader

后端 未结 5 683
日久生厌
日久生厌 2021-02-10 00:54

I\'ve converted my AsyncTask to an AsyncTaskLoader (mostly to deal with configuration changes). I have a TextView I am using as a progres

5条回答
  •  天涯浪人
    2021-02-10 01:39

    The best method is to use LiveData, 100% Working

    Step 1: Add lifecycle dependency or use androidx artifacts as yes during project creation

    implementation "androidx.lifecycle:lifecycle-livedata:2.1.0"
    

    Step 2: Create the loader class as follow, in loader create in public method to set the livedata that can be observed from activity or fragment. see the setLiveCount method in my loader class.

    package com.androidcodeshop.asynctaskloaderdemo;
    
    import android.content.Context;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.lifecycle.MutableLiveData;
    import androidx.loader.content.AsyncTaskLoader;
    
    import java.util.ArrayList;
    
    public class ContactLoader extends AsyncTaskLoader> {
    
    private MutableLiveData countLive = new MutableLiveData<>();
    
    
    synchronized public void setLiveCount(MutableLiveData observer) {
        countLive = (observer);
    }
    
    
    public ContactLoader(@NonNull Context context) {
        super(context);
    }
    
    @Nullable
    @Override
    public ArrayList loadInBackground() {
        return loadNamesFromDB();
    }
    
    private ArrayList loadNamesFromDB() {
    
        ArrayList names = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                names.add("Name" + i);
                countLive.postValue(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return names;
    }
    
    
    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        forceLoad(); // forcing the loading operation everytime it starts loading
    }
    }
    

    Step 3: Set the live data from activity and observe the change as follows

    package com.androidcodeshop.asynctaskloaderdemo;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.widget.Toast;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.lifecycle.MutableLiveData;
    import androidx.loader.app.LoaderManager;
    import androidx.loader.content.Loader;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.util.ArrayList;
    
    public class MainActivity extends AppCompatActivity implements 
    LoaderManager.LoaderCallbacks {
    
    private ContactAdapter mAdapter;
    private ArrayList mNames;
    private MutableLiveData countLiveData;
    private static final String TAG = "MainActivity";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mNames = new ArrayList<>();
        mAdapter = new ContactAdapter(this, mNames);
        RecyclerView mRecyclerView = findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(mAdapter);
        countLiveData = new MutableLiveData<>();
        countLiveData.observe(this, new androidx.lifecycle.Observer() {
            @Override
            public void onChanged(Integer integer) {
                Log.d(TAG, "onChanged: " + integer);
                Toast.makeText(MainActivity.this, "" + 
        integer,Toast.LENGTH_SHORT).show();
            }
        });
    
        // initialize the loader in onCreate of activity
        getSupportLoaderManager().initLoader(0, null, this);
        // it's deprecated the best way is to use viewmodel and livedata while loading data
    }
    
    @NonNull
    @Override
    public Loader onCreateLoader(int id, @Nullable Bundle args) {
    
        ContactLoader loader = new ContactLoader(this);
        loader.setLiveCount(countLiveData);
        return loader;
    }
    
    @Override
    public void onLoadFinished(@NonNull Loader load, ArrayList data) {
        mNames.clear();
        mNames.addAll(data);
        mAdapter.notifyDataSetChanged();
    }
    
    
    @Override
    public void onLoaderReset(@NonNull Loader loader) {
        mNames.clear();
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
    
    }
    

    Hope this will help you :) happy coding

提交回复
热议问题