Синхронизация с сервером
Я уже давно занимаюсь разработкой для Android и сейчас работаю с синхронизацией с моим сервером.
Краткое введение: я читал о Sync Adapter и знаю его роль, но я просто хочу знать, является ли это моим лучшим вариантом.
В моем приложении пользователь может нажать на кнопку, чтобы сообщить что-то важное для него. По клику я хотел бы обновить сервер, чтобы сохранить данные, а также уведомить своих родственников. Моя проблема заключается в следующем: пользователь может несколько раз нажать эту кнопку, чтобы включить и выключить ее, поэтому в этом случае я не хочу открывать связь с сервером каждый раз, когда пользователь нажимает кнопку, она может даже не изменить состояние с его предыдущее состояние.
Поэтому мой вопрос: подходит ли мне адаптер синхронизации, или я должен создать свой собственный класс для общения с сервером, который проверит это, а также получит срочные \ несрочные, как у Волли. Если бы кто-то мог уточнить точную работу Sync Adapter, я был бы очень признателен (это делает то, что я сказал?)
Если что-то не понятно, я был бы рад уточнить. Заранее спасибо.
4 ответа
Платформа синхронизации Android должна быть достаточно хороша для вашего использования. Если вы отметите синхронизацию по мере необходимости, система не запустит ее прямо сейчас, а отложит на некоторое время. Таким образом, если пользователь переключит кнопку назад, вы сможете заметить, что значение не изменилось. Sidenote: если вы используете ContentProvider
уведомляет SyncAdapter
автоматически, когда данные изменяются. Вы также можете запустить синхронизацию вручную, если это необходимо.
Что делает каркас синхронизации, так это просто вызывает метод (onPerformSync
). Вы можете реализовать это как хотите. Вы можете пропустить синхронизацию, если считаете, что последняя была слишком близкой, или обнаружили, что данные действительно изменились или они вернулись к исходному значению (например, вы можете сохранить значение "последней синхронизированной" в вашей базе данных, а затем сравнить его). к текущему значению в вашем onPerformSync
метод. Если то же самое, без изменений).
Бонус: вы сэкономите заряд батареи, так как среда синхронизации выполняет несколько последовательных синхронизаций в максимально возможной степени, ваши пользователи смогут управлять своими учетными записями в централизованном месте (настройки Android), отключить синхронизацию всей системы (подумайте о Sony режим выносливости, устанавливающий каждый SyncAdapter в паузу, пока активен).
Запустите адаптер синхронизации при изменении данных на устройстве. Этот параметр позволяет отправлять измененные данные с устройства на сервер и особенно полезен, если вам необходимо убедиться, что на сервере всегда находятся самые последние данные устройства. Эту опцию легко реализовать, если вы на самом деле храните данные у своего контент-провайдера. Если вы используете незавершенный контент-провайдер, обнаружение изменений данных может оказаться более сложным.
Запустите адаптер синхронизации в ответ на действие пользователя. Однако для обеспечения наилучшего взаимодействия с пользователем вы должны полагаться в первую очередь на один из более автоматизированных вариантов.
Вы можете периодически запускать свой адаптер синхронизации, устанавливая период ожидания между запусками, или запускать его в определенное время дня, или и то, и другое. Периодический запуск адаптера синхронизации позволяет вам приблизительно соответствовать интервалу обновления вашего сервера.
Вы могли бы также использовать другой подход, выдвигая ваш сервер с устройства, ваше приложение не должно время от времени запрашивать обновления, а сервер, который должен сказать "эй, у меня есть кое-что для вас".
Посмотрите на Google Cloud Messaging. С другой стороны, если вы предпочитаете подход, который пользователь должен специально запрашивать для своих обновлений, то вам не нужно беспокоиться о синхронизации адаптеров - конечно, это зависит от требований вашего приложения.
Тем не менее, я бы порекомендовал вам взглянуть на GCM, он более чистый и элегантный, чтобы сервер уведомлял его, а затем продолжал спрашивать.
Запуск адаптера синхронизации при изменении данных поставщика контента
public class MainActivity extends FragmentActivity {
...
// Constants
// Content provider scheme
public static final String SCHEME = "content://";
// Content provider authority
public static final String AUTHORITY = "com.example.android.datasync.provider";
// Path for the content provider table
public static final String TABLE_PATH = "data_table";
// Account
public static final String ACCOUNT = "default_account";
// Global variables
// A content URI for the content provider's data table
Uri mUri;
// A content resolver for accessing the provider
ContentResolver mResolver;
...
public class TableObserver extends ContentObserver {
/*
* Define a method that's called when data in the
* observed content provider changes.
* This method signature is provided for compatibility with
* older platforms.
*/
@Override
public void onChange(boolean selfChange) {
/*
* Invoke the method signature available as of
* Android platform version 4.1, with a null URI.
*/
onChange(selfChange, null);
}
/*
* Define a method that's called when data in the
* observed content provider changes.
*/
@Override
public void onChange(boolean selfChange, Uri changeUri) {
/*
* Ask the framework to run your sync adapter.
* To maintain backward compatibility, assume that
* changeUri is null.
ContentResolver.requestSync(ACCOUNT, AUTHORITY, null);
}
...
}
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// Get the content resolver object for your app
mResolver = getContentResolver();
// Construct a URI that points to the content provider data table
mUri = new Uri.Builder()
.scheme(SCHEME)
.authority(AUTHORITY)
.path(TABLE_PATH)
.build();
/*
* Create a content observer object.
* Its code does not mutate the provider, so set
* selfChange to "false"
*/
TableObserver observer = new TableObserver(false);
/*
* Register the observer for the data table. The table's path
* and any of its subpaths trigger the observer.
*/
mResolver.registerContentObserver(mUri, true, observer);
...
}
...
}