Объедините комнату и Retroffit с Dagger2 - PullRequest
0 голосов
/ 02 июля 2018

Как правильно создать DAO с помощью Room and Retrofit?

У меня есть такой модуль базы данных:

@Module
public class ApplicationDatabaseModule {

private final String mDatabaseName;
ApplicationDatabase mApplicationDatabase;

public ApplicationDatabaseModule(@ApplicationContext Context context, Class<? extends ApplicationDatabase> roomDataBaseClass, String databaseName) {
    mDatabaseName = databaseName;
    mApplicationDatabase = Room.databaseBuilder(context, roomDataBaseClass, mDatabaseName).build();
}

@Singleton
@Provides
ApplicationDatabase provideApplicationDatabase() {
    return mApplicationDatabase;
}

@Singleton
@Provides
CitiesDao provideCitiesDao() {
    return mApplicationDatabase.getCitiesDao();
}

}

класс POJO, как это:

@Entity
public class City {

@PrimaryKey
@ColumnInfo(name = "id")
private int cityId;

@ColumnInfo(name = "name")
private String cityName;

public int getCityId() {
    return cityId;
}

public void setCityId(int cityId) {
    this.cityId = cityId;
}

public String getCityName() {
    return cityName;
}

public void setCityName(String cityName) {
    this.cityName = cityName;
}

@Override
public String toString() {
    return "City [cityId = " + cityId + ", cityName = " + cityName + "]";
}
}

Интерфейс DAO, как это:

@Dao
public interface CitiesDao {

@Insert
void insertCities(City... cities);

@Query("SELECT * FROM City")
City[] queryCities();

}

И API для модернизации:

public interface CitiesApi {
@GET("/api/cities")
Call<City[]> requestCities();
}

Как я знаю, DAO отвечает за доступ к данным, включая данные, передаваемые через REST-клиент. Но эти две части представлены интерфейсами и встроены в отдельные классы. Как правильно внедрить DAO?

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

DAO отвечает за доступ к данным

да

, включая данные, переданные через REST-клиент.

Бог нет

Как правильно внедрить DAO?

Room уже генерирует правильный способ реализации вашего DAO на основе вашего интерфейса + аннотации, я думаю, что он называется CitiesDao_Impl.

Как правильно создать DAO с помощью Room and Retrofit?

Комната не знает о модернизации и не должна знать о модернизации. Он заботится только о сохранении локальных данных.

То есть ваш DAO должен выглядеть следующим образом:

@Dao
public interface CitiesDao {

    @Insert
    @Transaction
    void insertCities(City... cities);

    @Query("SELECT * FROM City")
    LiveData<List<City>> queryCities();

}

Так что вам на самом деле нужен работник, который будет извлекать новые данные в фоновом режиме, когда кеш недействителен (принудительно извлекает новые данные) или когда должна выполняться ваша задача синхронизации (например, когда устройство заряжается и Вы подключены к WIFI и находитесь с 2 до 7 утра - для этого вам понадобится WorkManager).

Немедленно получить новые данные, хотя это довольно просто, все, что вам нужно, это либо AsyncTask в одноэлементном контексте, который возвращает null из doInBackground, либо ваш собственный Исполнитель, которому вы отправляете фоновую задачу.

 public class FetchCityTask extends AsyncTask<Void, Void, Void> {
     ...

     @Override
     protected Void doInBackground(Void... params) {
         List<City> cities = citiesApi.requestCities().execute().body(); // TODO error handling
         citiesDao.insertCities(cities);
         return null;
     }
 }

А потом

new FetchCityTask(...).execute();

Теперь, когда эта задача будет запущена, ваш пользовательский интерфейс будет обновлен последними данными, наблюдая за данными LiveData, которые вы храните в ViewModel.

public class CitiesViewModel
        extends ViewModel {
    private final CitiesDao citiesDao;

    private LiveData<List<City>> liveResults;

    public CitiesViewModel(...) {
        ...
        liveResults = citiesDao.queryCities();
    }

    public LiveData<List<City>> getCities() {
        return liveResults;
    }
}

И

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    recyclerView = view.findViewById(R.id.recycler_view);
    CitiesViewModel viewModel = ViewModelProviders.of(this).get(CitiesViewModel.class, ...);

    ...
    viewModel.getTasks().observe(getViewLifecycle(), list -> {
        //noinspection Convert2MethodRef
        listAdapter.submitList(list);
    });
}
0 голосов
/ 02 июля 2018

Вы хотите создать класс репозитория для обработки ваших данных. Тогда вы просто взаимодействуете со своим хранилищем. Какой-то псевдокод для вас:

class Repository {
   private CitiesDao localSource;
   private CitiesApi remoteSource;

   public Repository() {
       //initialize objects here
   }

   City[] getCities() {
       if (networkIsAvailable) {
           City[] cities = remoteSource.requestCities();
           saveCitiesToDatabase(cities);
           return cities;
       } else {
           return localSource.queryCities();
       }
   }

   private void saveCitiesToDatabase(City[] cities) {
    //TODO save cities to databse
   }

}
...