Как уведомить о вызове Activity после завершения SyncAdapter?

В моем проекте Android я использую пользовательский SyncAdapter, который загружает данные и сохраняет их в локальной базе данных SQLite.

public class CustomSyncAdapter extends AbstractThreadedSyncAdapter {

    public CustomSyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
    }

    @Override
    public void onPerformSync(Account account,
                              Bundle extras,
                              String authority,
                              ContentProviderClient provider,
                              SyncResult syncResult) {

        // 1) Download data via AsyncTask
        // 2) Store data via ContentProvider
    }
}

Я планирую синхронизацию с основного Activity, используя ContentResolver, например...

ContentResolver.requestSync(account, Authentication.AUTHORITY, bundle);

Существует ли общий способ уведомления вызывающего Activity о завершении синхронизации?




Ответы (2)


Вы можете сделать это с помощью ContentResolver.notifyChange().

Итак, в вашем SyncAdapter вы бы сделали что-то вроде этого:

...
@Override
public void onPerformSync(Account account,
                          Bundle extras,
                          String authority,
                          ContentProviderClient provider,
                          SyncResult syncResult) {

    // 1) Download data via AsyncTask
    // 2) Store data via ContentProvider

    getContext().getContentResolver().notifyChange(<your_content_uri>, null, false);
}
...

Затем в действии вы используете ContentResolver.registerContentObserver():

public class MyActivity extends Activity  {

    private ContentObserver mObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
            public void onChange(boolean selfChange) {
                // Do something.
            }
        };
        getContentResolver().registerContentObserver(<your_content_uri>, mObserver);
    }

    @Override
    public void onDestroy() {
        getContentResolver().unregisterContentObserver(mObserver);
    }
}
person Blaz    schedule 04.02.2014
comment
ContentObserver требует передачи обработчика. notifyChange это то же самое сообщение, которое уже отправлено ContentProvider, я думаю?! Или какой Uri вы используете? - person JJD; 04.02.2014
comment
Я добавил Handler к своему ответу. Да, если ваш ContentProvider вызывает notifyChange, вам не нужно вызывать его вручную. - person Blaz; 04.02.2014
comment
Я думаю, что мне нужно пропустить Looper.getMainLooper, так как я уже работаю в потоке пользовательского интерфейса. В противном случае я попаду в java.util.concurrent.RejectedExecutionException. - Я думаю, вы комментируете Ничего не делать. должно быть что-то вроде интерфейса обновления. - person JJD; 05.02.2014
comment
Если вы не добавите Looper.getMainLooper(), Handler возьмет петлитель из текущего потока. Что в вашем случае является основным петлителем. Так что это не должно быть проблемой. - person Blaz; 05.02.2014

В свою деятельность вы можете добавить:

@Override
public void onResume() {
    super.onResume();
    mSyncMonitor = ContentResolver.addStatusChangeListener(
            ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE
                    | ContentResolver.SYNC_OBSERVER_TYPE_PENDING,
            this
    );
}

@Override
public void onPause() {
    ContentResolver.removeStatusChangeListener(mSyncMonitor);
    super.onPause();
}

@Override
public final void onStatusChanged(int which) {
    // TODO update activity data
}
person HotIceCream    schedule 22.10.2014