2012-10-16 21 views
11

Tôi muốn hiển thị ProgressBar trong ActionBar trong khi SyncAdapter của tôi đang tích cực đồng bộ hóa nội dung đến và từ web.SyncAdapter chạy hoạt ảnh - cách biết liệu SyncAdapter đang tích cực đồng bộ hóa

Tôi đã thử sử dụng SyncStatusObserver cùng với ContentProvider.addStatusChangeListener. Tuy nhiên, tôi không thể kiểm tra xem SyncAdapter có đang chạy hay không. Tôi chỉ có thể kiểm tra:

  1. SyncAdapter đang chờ sử dụng ContentResolver.isSyncPending
  2. SyncAdapter đang chờ HOẶC tích cực làm việc sử dụng ContentResolver.isSyncActive

Những lá cờ có thể được kết hợp: !isSyncPending && isSyncActive để nó có thể kiểm tra xem một SyncAdapter đang hoạt động tích cực và không có bất kỳ công việc đang chờ xử lý nào. Tuy nhiên, trong một số trường hợp, SyncAdapter đang hoạt động tích cực và có yêu cầu chờ xử lý thứ hai đang chờ nó.

Dường như đơn giản nhưng tôi không thể tìm ra cách giải quyết vấn đề này. Có ProgressBar hiển thị khi SyncAdapter không chạy đang cho người dùng ấn tượng rằng việc đồng bộ hóa rất chậm. Có nó không hiển thị ProgressBar làm cho người dùng nghĩ rằng không có gì đang xảy ra.

Giải pháp trên trong mã được hiển thị bên dưới. Chúng tôi đăng ký quan sát viên trong activity.onResume:

int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING | ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE; 
syncHandle = ContentResolver.addStatusChangeListener(mask, syncObserver); 

Các syncObserver được ở đây được định nghĩa là:

syncObserver = new SyncStatusObserver() 
{ 
    @Override 
    public void onStatusChanged(int which) 
    { 
     Account account = getSomeAccount(); 
     boolean syncActive = ContentResolver.isSyncActive(account, CONTENT_AUTHORITY); 
     boolean syncPending = ContentResolver.isSyncPending(account, CONTENT_AUTHORITY); 
     boolean isSynchronizing = syncActive && !syncPending; 
     updateRefreshButtonState(); 
    } 
} 

Trả lời

16

cuối cùng tôi đã tìm thấy một giải pháp cho vấn đề. Ý tưởng là sử dụng các phương pháp getCurrentSyncs() hoặc getCurrentSync() của ContentResolver, tùy theo điều kiện nào có sẵn. Các phương thức bên dưới sẽ kiểm tra xem hoạt động đồng bộ hóa có đang hoạt động cho tài khoản và quyền hạn hay không. Nó yêu cầu API cấp 8 (Froyo = Android 2.2).

private static boolean isSyncActive(Account account, String authority) 
{ 
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
    { 
     return isSyncActiveHoneycomb(account, authority); 
    } else 
    { 
     SyncInfo currentSync = ContentResolver.getCurrentSync(); 
     return currentSync != null && currentSync.account.equals(account) && 
       currentSync.authority.equals(authority); 
    } 
} 

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
private static boolean isSyncActiveHoneycomb(Account account, String authority) 
{ 
    for(SyncInfo syncInfo : ContentResolver.getCurrentSyncs()) 
    { 
     if(syncInfo.account.equals(account) && 
      syncInfo.authority.equals(authority)) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

Tích Cực sau đó đăng ký các bản cập nhật trong onResume() và sẽ hủy đăng ký trong onDestroy(). Ngoài ra, người ta phải cập nhật trạng thái theo cách thủ công trong onResume() để cập nhật trạng thái hiện tại.

Đây là triển khai thực hiện điều đó. Lớp con nên tự xác định

  • gì tài khoản để sử dụng (thực hiện getAccount())
  • gì authoritity sử dụng (các lĩnh vực CONTENT_AUTHORITY)
  • làm thế nào để hiển thị trạng thái sychronization (thực hiện updateState(boolean isSynchronizing))

Tôi hy vọng nó sẽ giúp ai đó trong tương lai.

import android.accounts.Account; 
import android.annotation.TargetApi; 
import android.app.Activity; 
import android.content.ContentResolver; 
import android.content.SyncInfo; 
import android.content.SyncStatusObserver; 
import android.os.Build; 
import android.os.Bundle; 

public abstract class SyncActivity extends Activity 
{ 
    private static final String CONTENT_AUTHORITY = "com.example.authority"; 
    private Object syncHandle; 
    private SyncStatusObserver observer; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 

     observer = new SyncStatusObserver() 
     { 
      @Override 
      public void onStatusChanged(int which) 
      { 
       runOnUiThread(new Runnable() 
       { 
        @Override 
        public void run() 
        { 
         Account account = getAccount(); 
         boolean isSynchronizing = 
           isSyncActive(account, CONTENT_AUTHORITY); 
         updateState(isSynchronizing); 
        } 
       }); 
      } 
     }; 
    } 

    @Override 
    protected void onResume() 
    { 
     super.onResume(); 

     // Refresh synchronization status 
     observer.onStatusChanged(0); 

     // Watch for synchronization status changes 
     final int mask = ContentResolver.SYNC_OBSERVER_TYPE_PENDING | 
       ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE; 
     syncHandle = ContentResolver.addStatusChangeListener(mask, observer); 
    } 

    @Override 
    protected void onPause() 
    { 
     super.onPause(); 

     // Remove our synchronization listener if registered 
     if (syncHandle != null) 
     { 
      ContentResolver.removeStatusChangeListener(syncHandle); 
      syncHandle = null; 
     } 
    } 

    private static boolean isSyncActive(Account account, String authority) 
    { 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
     { 
      return isSyncActiveHoneycomb(account, authority); 
     } else 
     { 
      SyncInfo currentSync = ContentResolver.getCurrentSync(); 
      return currentSync != null && currentSync.account.equals(account) 
        && currentSync.authority.equals(authority); 
     } 
    } 

    @TargetApi(Build.VERSION_CODES.HONEYCOMB) 
    private static boolean isSyncActiveHoneycomb(Account account, 
                 String authority) 
    { 
     for(SyncInfo syncInfo : ContentResolver.getCurrentSyncs()) 
     { 
      if(syncInfo.account.equals(account) && 
        syncInfo.authority.equals(authority)) 
      { 
       return true; 
      } 
     } 
     return false; 
    } 

    protected abstract Account getAccount(); 
    protected abstract void updateState(boolean isSynchronizing); 
} 
+1

Đối với Eclair, Froyo, Gingerbread, giải pháp ở trên chỉ hoạt động nếu thiết bị chỉ có một tài khoản. Nếu có nhiều tài khoản tồn tại trên thiết bị, tài khoản đầu tiên sẽ chỉ được đồng bộ hóa; phần còn lại bị bỏ qua. – ChuongPham

Các vấn đề liên quan