Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Android

Cách sử dụng Android Loader (CursorLoader) tải danh bạ

Giới thiệu

Lưu ý quan trọng: android.app.Loader và CursorLoader đã bị deprecated từ API 28 (Android 9.0). Google khuyến nghị sử dụng ViewModel + LiveData + Room hoặc Flow/Coroutines cho tải dữ liệu bất đồng bộ. Bài viết này giải thích cách cũ để bảo trì code legacy.

Các bước thực hiện (Cách cũ - Deprecated)

Bước 1: Tạo dự án & Giao diện

Layout: ListView hiển thị tên liên hệ.

Bước 2: MainActivity.java (Sử dụng LoaderManager)

package com.example.myapplication;

import android.Manifest;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SimpleCursorAdapter;
import android.widget.ListView;

public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {

    private static final int LOADER_CONTACTS = 100;
    private static final int PERMISSION_CONTACTS = 101;
    private static final String[] PROJECTION = {
            ContactsContract.Contacts._ID,
            ContactsContract.Contacts.DISPLAY_NAME
    };

    ListView lstContact;
    SimpleCursorAdapter adapter;
    String[] from = {ContactsContract.Contacts.DISPLAY_NAME};
    int[] to = {android.R.id.text1};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        adapter = new SimpleCursorAdapter(this,
                android.R.layout.simple_list_item_1, null, from, to, 0);

        lstContact = findViewById(R.id.list);
        lstContact.setAdapter(adapter);

        // Kiểm tra quyền
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS}, PERMISSION_CONTACTS);
        } else {
            getLoaderManager().initLoader(LOADER_CONTACTS, null, this);
        }
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        if (id == LOADER_CONTACTS) {
            return new CursorLoader(this,
                    ContactsContract.Contacts.CONTENT_URI,
                    PROJECTION, null, null, null);
        }
        return null;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        adapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        adapter.swapCursor(null);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == PERMISSION_CONTACTS
                && grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            getLoaderManager().initLoader(LOADER_CONTACTS, null, this);
        }
    }
}

Cách hiện đại (Khuyến nghị) - ViewModel + LiveData + Room

1. Entity & DAO

@Entity
public class Contact {
    @PrimaryKey
    public long id;
    public String name;
    public String phone;
}

@Dao
public interface ContactDao {
    @Query("SELECT * FROM contact")
    LiveData<List<Contact>> getAllContacts();

    @Insert
    void insertAll(List<Contact> contacts);
}

2. Repository

public class ContactRepository {
    private ContactDao dao;
    private LiveData<List<Contact>> allContacts;

    public ContactRepository(Application app) {
        AppDatabase db = AppDatabase.getInstance(app);
        dao = db.contactDao();
        allContacts = dao.getAllContacts();
    }

    public LiveData<List<Contact>> getAllContacts() {
        return allContacts;
    }
}

3. ViewModel

public class ContactViewModel extends AndroidViewModel {
    private ContactRepository repository;
    public LiveData<List<Contact>> allContacts;

    public ContactViewModel(Application app) {
        super(app);
        repository = new ContactRepository(app);
        allContacts = repository.getAllContacts();
    }
}

4. Activity/Fragment quan sát

ContactViewModel vm = ViewModelProviders.of(this).get(ContactViewModel.class);
vm.allContacts.observe(this, contacts -> {
    // Cập nhật RecyclerView adapter
    adapter.submitList(contacts);
});

Chạy ứng dụng (cách cũ)

Nhấn Run. Danh sách liên hệ tải nền (background thread) và hiển thị trên ListView.

Cách sử dụng Android Loader (CursorLoader) tải danh bạ

Tóm tắt

  • Loader quản lý vòng đời tải dữ liệu tự động (xoay màn hình không tải lại).
  • Đã deprecated - không dùng cho project mới.
  • Dùng ViewModel + LiveData + Room/Paging 3 cho kiến trúc hiện đại.