Содержание статьи
- Опять теория
- Получение данных
- Разбор ответа
- API
- Хранение данных
- Вот и все
Опять теория
Для получения записей со стены используется метод wall.get.
Он вернет нам массив записей (JSON), начинaя с последней (если нам нужно получать записи с начала списка, то придется использовать в запросе параметр
Код:
offset
Код:
соunt
Стоит отметить, что пока этот метод построен не очень гибко. Придется делать два запроса к API вместо одного, первый раз — чтобы получить количество записей (count), а второй раз — уже нужные записи, используя первое значение как смещение. Записи в массиве будут располагаться в порядке от ранних к поздним.
У каждого элемента массива записей со стены может быть до десяти приложений (докумeнты, музыка, видео, фото). Вот пример ответа:
Код:
response:{ count:65, items:[ { id:92, from_id:-50536551, owner_id:-50536551, date:1469733672, marked_as_ads:0, post_type:'post', text:'Привет ][акер!', can_edit:1, created_by:3102253, can_delete:1, can_pin:1, attachments:[ { type:'photo', photo:{ id:374032462, album_id:-7, owner_id:3102253, photo_75:'https://pp.vk.me/...ad5/JN_ChKLiMZo.jpg', photo_130:'https://pp.vk.me/...ad6/Z-84c1FuwVc.jpg', photo_604:'https://pp.vk.me/...ad7/o79JN_hwnWs.jpg', width:350, height:163, text:'Original: https://static38.cmtt.ru/comment-media/77/f0/00/0e8971de9c4360.jpg', date:1435299352, post_id:1003, access_key:'1b927475e9be6cedd1' } }, { type:'video', video:{ id:171623222, owner_id:-50536551, title:'Напоминатель паролей', duration:90, description:'https://play.goog...delphi.wifipassword', date:1452846402, views:14, comments:0, photo_130:'https://pp.vk.me/...ideo/s_31105838.jpg', photo_320:'https://pp.vk.me/...ideo/l_88896102.jpg', photo_800:'https://pp.vk.me/...ideo/x_c377669a.jpg', access_key:'71fedc69404803dcb7', can_edit:1, can_add:1 } }, { type:'audio', audio:{ id:456239307, owner_id:2000390511, artist:'Научно-технический рэп', title:'Тыж программист', duration:172, date:1469733672, url:'https://cs1-32v4....3XvIToniOQ6tamk8E7A', lyrics_id:196340205, genre_id:3 } }, { type:'doc', doc:{ id:422991754, owner_id:3102253, title:'Французские переменные.txt', size:4017, ext:'txt', url:'https://vk.com/do...c46f98d38&api=1', date:1443852692, type:1, access_key:'38855b19f953ffaa11' } } ], post_source:{ type:'vk' }, comments:{ count:0, can_post:1 }, likes:{ count:0, user_likes:0, can_like:1, can_publish:1 }, reposts:{ count:0, user_reposted:0 } } ] }
Код:
type
Код:
text
Код:
photo
Для обработки видео нам нужно получить его
Код:
id
Код:
video.get
Код:
videos
Код:
owner_id + id (-50536551_171623222)
Код:
owner_id
Код:
-
Код:
response:{ count:1, items:[ { id:171623222, owner_id:-50536551, title:'Напоминатель паролей', duration:90, description:'https://play.goog...delphi.wifipassword', date:1452846402, views:14, comments:0, photo_130:'https://pp.vk.me/...ideo/s_31105838.jpg', photo_320:'https://pp.vk.me/...ideo/l_88896102.jpg', photo_800:'https://pp.vk.me/...ideo/x_c377669a.jpg', files:{ external:'http://www.youtub...watch?v=vdacaryKf1A' }, player:'https://www.youtu...ryKf1A?__ref=vk.api', can_edit:1, converting:0, can_add:1 } ] }
Приложение с типом
Код:
audio
Код:
doc
Получение данных
Для клиентского приложения важно получить данные из сети, сохранить их и отобразить пользователю. Способов работы с сетью предостаточно — это могут быть стандартные инструмeнты или сторонние библиотеки. Для работы с интернетом в SDK есть стандартный класс URLConnection. Ответ нужно разбирать вручную и как-то обрабатывать. Обычно для ответов собирают массив классов, где классы опиcывают объекты из API.
Сегодня для работы с сетью многие предпочитают использовать стоpонние инструменты. Часто это вызвано необходимостью обеспечивать адeкватную работоспособность при плохой связи (да-да, во многих местах нашей обшиpной родины качество мобильного интернета оставляет желать лучшего — операторы связи арендуют друг у друга оборудование, и в пиковые часы оно бывает тупо перегружено).Сейчас в отрасли стандартом де-факто стало использование связки Retrofit + OkHttp. Хорошую статью по ее применению ты найдешь здесь. Удобна эта связка тем, что позволяет работать с сетью как синхронно, так и асинхронно, что очень важно, поскольку Андpоид не дает работать с сетью в главном потоке.
Разбор ответа
Разбор ответов сервера делается автоматически, через механизм описания модели данных. Проиллюстрирую этот процесс кодом. Здесь мы в главном потоке запрашиваем список новых GIF-картинок для таблички с котами:
Код:
CatApiInterface client = ServiceGenerator.createService(CatApiInterface.class); dataCall = client.getCats("-120909644", "10", String.valueOf(offset)); dataCall.enqueue(new Callback<Data>() { @Override public void onResponse(Call<Data> call, Response<Data> response) { //android.os.Debug.waitForDebugger(); if (response.isSuccessful()) { // request successful (status code 200, 201) Data result = response.body(); LinkedHashSet<CatStore> newStore = new LinkedHashSet<>(); for (Data.Response cat : result.responses) { newStore.add(new CatStore(cat.attachment.doc.url.split("\\?")[0], false, Integer.parseInt(cat.text.substring(0, cat.text.indexOf("X"))), Integer.parseInt(cat.text.substring(cat.text.indexOf("X") + 1) ))); } newStore.addAll(mCatsSet); mCatsSet = newStore; if (mCatsAdapter != null) { mCatsAdapter.applyAndAnimateAdditions(new ArrayList<>(newStore)); } else { mCatsAdapter = new CatsAdapter(mCatsSet, MainActivity.this, Glide.with(MainActivity.this)); setupRecyclerView(mRecyclerView); } onItemsLoadComplete(); } else { Toast.makeText(getApplicationContext(), R.string.error_loading, Toast.LENGTH_SHORT).show(); onItemsLoadComplete(); } } @Override public void onFailure(Call<Data> call, Throwable t) { Toast.makeText(getApplicationContext(), R.string.error_loading, Toast.LENGTH_SHORT).show(); onItemsLoadComplete(); } });
API
Работа с методами API описана в интерфейсе:
Код:
public interface CatApiInterface { @GET("/method/wall.get") Call<Data> getCats(@Query("owner_id") String owner_id, @Query("count") String count, @Query("offset") String offset); @GET("method/wall.get?owner_id=-120909644&count=1") Call<WallData> getCatsNumber(); }
Код:
JsonDeserializer
Код:
HttpLoggingInterceptor
Код:
public class ServiceGenerator { public static final String API_BASE_URL = "https://api.vk.com"; private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL); public static <S> S createService(Class<S> serviceClass) { // Крутой лог по запpосам HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); // Свой парсер JSON Type responseListType = new TypeToken<List<Data.Response>>() { }.getType(); Gson gson = new GsonBuilder().registerTypeAdapter(responseListType, new JsonDeserializer<List<Data.Response>>() { @Override public List<Data.Response> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { List<Data.Response> responses = new ArrayList<>(); if (json.isJsonArray()) { for (JsonElement jsonElement : ((JsonArray) json)) { if (jsonElement.isJsonObject()) { Data.Response resp = context.deserialize(jsonElement, Data.Response.class); responses.add(resp); } } return responses; } return context.deserialize(json, typeOfT); } }).create(); // Запуск OkHttpClient client = new OkHttpClient.Builder().addInterceptor(logging).build(); builder.addConverterFactory(GsonConverterFactory.create(gson)); Retrofit retrofit = builder.client(client).build(); return retrofit.create(serviceClass); } }
Код:
public class Data { @SerializedName("response") @Expose public List<Response> responses; public class Response { @SerializedName("text") @Expose public String text; @SerializedName("attachment") @Expose public Attachment attachment; public class Attachment { @SerializedName("doc") @Expose public Doc doc; } public class Doc { @SerializedName("url") @Expose public String url; } } }
Работа с Glide:
Код:
Glide.load(URL) .diskCacheStrategy(DiskCacheStrategy.SOURCE) .into(imageView);
Хранение данных
Работа с видео, аудио и базами данных — темы обширные и достойные отдельных статей. И по этим направлениям андроид-кодеры имеют неплохой простор для творчества. В качестве БД можно использовать родную SQLite (кстати, создатели Telegram пересобрали ее и получили нехилый прирост производительности), кому-то нpавится библиотека Realm — по некоторым тестам она в разы обгоняет SQLite.
Если структура данных не очень сложная, то можно наш массив классов сохранить как текст (gson) в SharedPreferences:
Код:
SharedPreferences sp = getPreferences(MODE_PRIVATE); SharedPreferences.Editor editor = sp.edit(); Gson gson = new Gson(); String json = gson.toJson(mCatsSet); editor.putString("cats", json); editor.apply();
Код:
SharedPreferences sp = getPreferences(MODE_PRIVATE); Gson gson = new Gson(); String json = sp.getString("cats", null); Type type = new TypeToken<Set<CatStore>>() { }.getType(); if (json != null) mCatsSet = gson.fromJson(json, type);
Код:
compile 'com.google.code.gson:gson:2.6.2'
Вот и все
Этой статьей я закaнчиваю наш мини-цикл по использованию возможностей VK.com в качестве бесплатного бэкенда для твоих приложений. Надеюсь, пoлученные знания помогут тебе написать настоящий шедевр и сэкономить при этом нeмного денежек. Удачи и до новых встреч на наших виртуальных страницах!