Клиент-серверное взаимодействие под android в деталях
DESCRIPTION
TRANSCRIPT
![Page 1: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/1.jpg)
Клиент-серверное взаимодействие под Android
в деталях
Кирилл Зотин
Android dev lead
23.04.2011
![Page 2: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/2.jpg)
Введение
• Преимущества родных приложений над мобильными версиями сайтов
• Специфика мобильных приложений:
Document-ориентированая модель
VS
Database-ориентированная модель
![Page 3: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/3.jpg)
Преимущества над мобильными версиями сайтов.
• Тесная интеграция с платформой
• Улучшение поведения платформы
• Фоновая работа
• Более высокая скорость работы
• "родной" пользовательский интерфейс
![Page 4: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/4.jpg)
Document-ориентированаямодель данных
![Page 5: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/5.jpg)
Database-ориентированная модель данных
![Page 6: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/6.jpg)
Типичная реализация
![Page 7: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/7.jpg)
О проблеме
• OS в любой момент может остановить процесс
• Данные не всегда сохранены
![Page 8: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/8.jpg)
Правильная реализация1:Service API
![Page 9: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/9.jpg)
Правильная реализация2:Content Provider API
![Page 10: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/10.jpg)
Network-MVC
![Page 11: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/11.jpg)
Правильная реализация3:Content Provider + SyncAdapter
![Page 12: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/12.jpg)
Tips & Tricks
• Выполняйте запросы к БД не в UI потоке
• Используйте транзакции
• Делайте код хорошо читаемым
• Используйте Gzip сжатие
• Android 3.0: Loaders
• Удобный класс IntentService
![Page 13: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/13.jpg)
Выполняйте запросы к БД не в UI потоке
• Используйте (Notifying)AsyncQueryHandler
public class YourActivity extends Activity implements AsyncQueryListener {
@Override
public void onQueryComplete(int token, Object cookie,
final Cursor cursor) {
startManagingCursor(cursor);
. . .
}
}
![Page 14: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/14.jpg)
Используйте транзакции
@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
final SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
db.beginTransaction();
try {
final int numOperations = operations.size();
final ContentProviderResult[] results = new ContentProviderResult[numOperations];
for (int i = 0; i < numOperations; i++) {
results[i] = operations.get(i).apply(this, results, i);
}
db.setTransactionSuccessful();
return results;
} finally {
db.endTransaction();
}
![Page 15: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/15.jpg)
Группируйте детали запросов в одном месте
ПлохоCursor mCursor = query(true,
DATABASE_TABLE_EMAIL,
new String[] {
KEY_ROWID, KEY_EMAIL_NAME
},
KEY_ROWID + "=" + rowId,
null, null, null, null, null);
if (mCursor.moveToFirst()) {
long id = mCursor.getLong(
mCursor.getColumnIndexOrThrow(KEY_ROWID));
String name = mCursor.getString(
mCursor.getColumnIndexOrThrow(KEY_EMAIL_NAME));
}
Хорошоinterface ReviewsQuery {
final String[] PROJECTION = new String[] {Reviews._ID,Reviews.TITLE,Reviews.SUBTITLE,Reviews.IMG_URL_SMALL,Reviews.ARTICLE_ID
};int ID = 0;int TITLE = 1;int SUBTITLE = 2;int IMG_URL = 3;int ARTICLE_ID = 4;
String DEFAULT_SORT = Reviews.DATE + " desc";}...startAsyncQuery(QUERY_REVIEWS_ITEMS, null,
Reviews.CONTENT_URI,ReviewsQuery.PROJECTION,selection, null,ReviewsQuery.DEFAULT_SORT);
…final String url =
getCursor().getString(ReviewsQuery.IMG_URL);
![Page 16: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/16.jpg)
Используйте сжатие Gzip
HttpGet request = new HttpGet(uri);
request.addHeader("Accept-Encoding", "gzip");
HttpResponse response = getHttpClient().execute(request);
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null &&
contentEncoding.getValue().equalsIgnoreCase("gzip")) {
is = new GZIPInputStream(is);
}
![Page 17: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/17.jpg)
Honeycomb API: CursorLoader
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getLoaderManager().initLoader(0, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
final String eventId = getArguments().getString(EXTRA_EVENT_ID);
return new CursorLoader(getActivity(),
Events.CONTENT_URI,
EventQuery.PROJECTION,
EventQuery.SELECTION, new String[] {eventId}, null);
}
![Page 18: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/18.jpg)
Использование IntentService
• Для обработки Intent стартует Service
• Запрос обрабатывается в отдельном потоке
• Параллельные запросы кладутся в одну очередь.
![Page 19: Клиент-серверное взаимодействие под android в деталях](https://reader031.vdocuments.site/reader031/viewer/2022020122/54c3f4b74a7959285f8b4589/html5/thumbnails/19.jpg)
Выводы
• Не обрабатывайте сетевые операции в Activity, используйте Service
• Сохраняйте данные часто
• Все запросы к БД – в отдельный поток
• Минимизируйте трафик сетевых операций
• Используйте локальный кэш данных