Запрос номера, который возвращает список <Object>, останавливает приложение - PullRequest
0 голосов
/ 15 апреля 2020

Я попытался с помощью приведенного ниже кода загрузить некоторые данные из моей базы данных и отобразить их в действии:

PhoneNumberViewModel phoneNumberViewModel =
        new ViewModelProvider(WorksideContactCard.this).get(PhoneNumberViewModel.class);

phoneNumberViewModel
    .getPhoneNumbersById(contactID)
    .observe(this,
             numbers -> {
                 phoneNumberList = numbers;
             });

Если быть точным, мне не нужно наблюдать за изменением данных, так как данные будет обновлен, если деятельность возобновится. Но приведенный выше код останавливает мое приложение, хотя я обращаюсь к БД с помощью AsyncTask в моем другом классе.

Почему это может быть так?

РЕДАКТИРОВАТЬ:

PhoneNumberViewModel.class:

public class PhoneNumberViewModel extends AndroidViewModel {
    private PhoneNumberRepository phoneNumberRepository;
    private LiveData<List<PhoneNumber>> allPhoneNumbers;

    public PhoneNumberViewModel(@NonNull Application application) {
        super(application);
        phoneNumberRepository = new PhoneNumberRepository(application);
        allPhoneNumbers = phoneNumberRepository.getAllPhoneNumbersLive();
    }

    public void insert(PhoneNumber phoneNumber) {
        System.out.println("[PhoneNumberRepository] Adding new phoneNumber");
        phoneNumberRepository.insert(phoneNumber);
    }

    public void update(PhoneNumber phoneNumber) {
        phoneNumberRepository.update(phoneNumber);
    }

    public void delete(PhoneNumber phoneNumber) {
        phoneNumberRepository.delete(phoneNumber);
    }

    public LiveData<List<PhoneNumber>> getAllPhoneNumbers() {
        return allPhoneNumbers;
    }

    public LiveData<List<PhoneNumber>> getPhoneNumbersById(long contactId)
            throws ExecutionException, InterruptedException {
        return phoneNumberRepository.getPhoneNumbersByContactId(contactId);
    }

PhoneNumberRepository.class

public class PhoneNumberRepository {
    private PhoneNumberDao phoneNumberDao;
    private LiveData<List<PhoneNumber>> allPhoneNumbers;
    private LiveData<List<PhoneNumber>> phoneNumbersByIdList;

    public PhoneNumberRepository(Application application) {

        WorksideDatabase database = WorksideDatabase.getInstance(application);
        phoneNumberDao = database.phoneNumberDao();
        allPhoneNumbers = phoneNumberDao.getAllPhoneNumbers();
    }

    ...

    public LiveData<List<PhoneNumber>> getAllPhoneNumbersLive() {
        return allPhoneNumbers;
    }

    public void deleteAllPhoneNumbers() {
        new DeleteAllPhoneNumbersAsyncTask(phoneNumberDao).execute();
    }

    public LiveData<List<PhoneNumber>> getPhoneNumbersByContactId(long id)
            throws ExecutionException, InterruptedException {
        return new SelectPhoneNumberByIdAsyncTask(phoneNumberDao, id).get();
    }

    private static class SelectPhoneNumberByIdAsyncTask
            extends AsyncTask<Long, Void, LiveData<List<PhoneNumber>>> {

        private PhoneNumberDao phoneNumberDao;
        private Long ID;

        private SelectPhoneNumberByIdAsyncTask(PhoneNumberDao phoneNumberDao, Long contactId) {
            this.phoneNumberDao = phoneNumberDao;
            ID = contactId;
        }

        @Override
        protected LiveData<List<PhoneNumber>> doInBackground(Long... contactId) {

            ID = contactId[0];

            return phoneNumberDao.getPhoneNumbersById(ID);
        }
    }

    ...
}

PhoneNumberDao.class:

@Dao
public interface PhoneNumberDao {

    @Insert
    void insert(PhoneNumber phoneNumber);

    @Update
    void update(PhoneNumber phoneNumber);

    @Delete
    void delete(PhoneNumber phoneNumber);

    // Probably uneeded method
    @Query("DELETE FROM phone_numbers_table")
    void deleteAllPhoneNumbers();

    // Delete entry/entries by ID
    @Query("DELETE FROM phone_numbers_table WHERE id = :phoneNumberId")
    void deleteByPhoneNumberId(long phoneNumberId);

    // Retrieve entry/entries by contact ID
    //    @Query("SELECT * FROM phone_numbers_table WHERE contact_id = :contactId")
    //    List<PhoneNumber> getPhoneNumbersById(long contactId);

    // Retrieve all saved phone numbers in LiveData format
    @Query("SELECT * FROM phone_numbers_table")
    LiveData<List<PhoneNumber>> getAllPhoneNumbers();

    @Query("SELECT * FROM phone_numbers_table WHERE contact_id = :contactId")
    LiveData<List<PhoneNumber>> getPhoneNumbersById(long contactId);

    @Query("SELECT * FROM phone_numbers_table")
    List<PhoneNumber> getAll();
}

1 Ответ

0 голосов
/ 15 апреля 2020
return new SelectPhoneNumberByIdAsyncTask(phoneNumberDao, id).get(); 

в этом ваша проблема, вызов .get () блокирует основной поток, я бы предложил переключиться на Kotlin и использовать Coroutines или здесь вы можете справиться с этим с помощью обратных вызовов, а не с помощью AsyncTask.get (), который блокирует основной поток. Также BTW Asyn c Задача будет устаревшей, как я слышал, так что имейте это в виду. Это одно из решений проблемы

public class Repository implements 
SelectPhoneNumberByIdAsyncTask.OnPhoneNumberFound {


@Override
public void onPhoneNumberFound(LiveData<List<Object>> list) {
   //you can get the data you want here
}



} 


 class SelectPhoneNumberByIdAsyncTask extends AsyncTask<Long, Void, 
  LiveData<List<PhoneNumber//Correct this>>> {

interface OnPhoneNumberFound{
    void onPhoneNumberFound(LiveData<List<PhoneNumberDao>> list);
}
OnPhoneNumberFound mListener;


private PhoneNumberDao phoneNumberDao;
private Long ID;

private SelectPhoneNumberByIdAsyncTask(Object phoneNumberDao, Long contactId) {
    this.phoneNumberDao = phoneNumberDao;
    ID = contactId;
}

@Override
protected LiveData<List<Object>> doInBackground(Long... contactId) {
    ID = contactId[0];
    mListener.onPhoneNumberFound(phoneNumberDao.getPhoneNumbersById(ID));
    return null;
}

}

использовать вызов .execute () вместо .get ()

...