Хочу разобраться разобраться как правильно организовать REST-клиент.
Есть API, которая по запросу выдает JSON объекты.
Нужно построить список ListView(или лучше использовать RecyclerView?) из этих JSON.
Как я это все делаю:
public class MainActivity extends AppCompatActivity {
private static final String API = "https://api.github.com";
ListView listView;
UserAdapter adapter;
DBHandler mDBhandler;
int lastUserIDinList=0;
//начальное кол-во пользователей в списке
int initialAmountUsers=10;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDBhandler = new DBHandler(this);
listView = (ListView) findViewById(R.id.listview);
adapter = new UserAdapter(MainActivity.this, new ArrayList
new CountUserInDB().execute();
listView.setOnScrollListener(new EndlessScrollListener() {
@Override
public boolean onLoadMore(int page, int totalItemsCount) {
loadUsers(1);
return true;
}
});
}
//получаем от API объекты, ждем коллбэк и запускаем AsyncTask запись в базу(в качестве параметра передаем список моделей)
void loadUsers(int count){
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(API).build();
GitAPI git = restAdapter.create(GitAPI.class);
//полчаем от АПИ пользователей с ид больше lastUserIDinList. количество пользователей в ответе - count
git.getNextUsers(lastUserIDinList, count, new Callback
@Override
public void failure(RetrofitError error) {
Toast.makeText(getApplicationContext(), error.getMessage(),
Toast.LENGTH_LONG).show();
}
});
}
//get arralist of users and write it to db
class WriteToDB extends AsyncTask
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Integer doInBackground(ArrayList
//get id of userd from what need to read from db
class ReadFromDB extends AsyncTask
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected ArrayList
@Override
protected void onPostExecute(ArrayList
//get arralist of users and add it to adapter
class DisplayUserInListView extends AsyncTask
@Override
protected Void doInBackground(ArrayList
class CountUserInDB extends AsyncTask
int lastUserIDinTable=-1;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Integer doInBackground(Void... params) {
//получаем ИД последней записи в таблице
lastUserIDinTable=mDBhandler.getLastUseID();
//получаем количество пользователей в таблице
return mDBhandler.getUserCount();
}
@Override
protected void onPostExecute(Integer userCount) {
super.onPostExecute(userCount);
if(userCount==0){
//база пуста, загрузим 10 пользователей для начала
loadUsers(10);
}
if(userCount>=initialAmountUsers){
//в базе больше 10 пользователей, что достаточно для начала - читаем из базы.
new ReadFromDB().execute(0);
}
if(userCount>0 && userCount
}
}
}
У меня такое чувство, что сделал какой-то велосипед.
Какие есть советы по улучшение(или переделыванию полностью) логики ?
Не много ли я использую AsyncTask ?
Интересны любые советы по грамотному получению JSON объектов, использованию API, добавлением итемов в список..
UPD:
Почитав статьи, пришел к выводу, что REST клиента на андроиде нужно делать по двум вариантам:
1)Создавать сервис, в котором будут загружаться данные с API(), парситься, записываться в базу и потом передавать в активити сообщение, что надо обновить список. Активити как получит такое уведомление, с помощью CursorLoader'а грузит данные из таблицы и добавляет их адаптеру списка.
2)Не создавать сервисов, а в активити с помощью AsyncTaskLoader'ов(для получения инфы в фоне, при этом еще использовать Retrofit) и CursorLoader'ов, с помощью которых читать/писать базу.
Какой из этих подходов более грамотный ? Возможно есть какие-то дополнения или уточнения к этим подходам ?
Ответ
Многократно уже отписывался на эту тему, как писать REST клиента. Не поленюсь написать еще раз:
Через сервис тягаем JSON объекты из сети и складываем в SQLite БД
Над SQLite БД создаем ContentProvider и через CursorLoader организуем подпитку CursorAdapter, который и будет адаптером для ListView или RecyclerView
Вопрос выбора ListView или RecyclerView - это вопрос не только вкуса, но и квалификации (все таки). Как показывает опыт RecyclerView сложнее в понимании, но дает гораздо большую свободы в плане управления списком. Я бы рекомендовал начинать с ListView и только потом приступать к RecyclerView
Для работы с JSon лучшим инструментом является Google Gson - берите его и даже не сомневайтесь. Функция Gson очень простая, но важная: это трансляция вашего Java объекта в Json строку и обратно. По сути вместо рутинного парсинга json строки вы будете иметь дело с интеллигентными Java классами.
Часто при работе с Rest требуется реализация функциональности Pull-To-Refresh - ну то есть обновление списка при вытягивании вверх/вниз. В сети есть огромное количество реализаций Pull-To-Refresh. Я пользовался этим проектом - но он сейчас мертвый. Недавно в суппорт либах появился новый виджет: SwipeRefreshLayout я лично не пользовался не знаю как с ним работать. Те из знакомых кто пользовались - пищат от восторга. У меня нет оснований не доверять им.
P.S. Для RecyclerView организовать CursorAdapter напрямую не получится, нужно будет применить эту наработку
Update
Создавать сервис, в котором будут загружаться данные с API(), парситься,
записываться в базу и потом передавать в активити сообщение, что надо
обновить список. Активити как получит такое уведомление, с помощью
CursorLoader'а грузит данные из таблицы и добавляет их адаптеру списка.
В качестве сервиса подойдет IntentService, который можно запускать по таймеру и/или через событие генерируемое при Pull-To-Refresh
Не надо никак уведомлять Activity о том, что БД изменилось - CursorLoader сам будет автоматом подгружать обновленные данные при изменении БД через соответствующий Observer (в случае RecyclerView), а в случае CursorAdapter это уже будет "из коробки"
Комментариев нет:
Отправить комментарий