2012-11-30 47 views
2

TokenCache類傳遞給Facebook類做save()load()令牌的功能時。 TokenCache具有以下功能:困難的問題實施了多線程返回一個值

public abstract void save(Bundle bundle); 
public abstract Bundle load(); 

現在,我想這樣做,保存和加載在多線程,所以我運行一個load()AsyncTask。問題是它已經被設計爲返回一個Bundle!如何實現它,以便僅在AsyncTask完成時返回值?

+1

如果只有當它完成後返回的值,它不會真的是一個的AsyncTask,現在,不是嗎?你需要做的是重構它,以便它接受一個匿名類和一個接受返回值作爲參數的單一方法,或者一些其他類似的異步處理結果的機制。 – jrajav

+0

是的,它是返回值的函數。它被設計成爲開發人員提供實現的抽象。問題是加載可能是一個長期的操作。 – Emerald214

回答

1

只需在你的TokenCache實現你的load()方法返回捆綁的領域。只要確保你還沒有將TokenCache的引用傳遞給FB,直到該Bundle被一些init(bundle)方法初始化爲止,例如,

static class BundleRetrievalTask extends AsyncTask<String, Void, Bundle> { 

     @Override 
     protected Bundle doInBackground(String... strings) { 
      return someLongOperationThatFetchesBundle(strings[0]); 
     } 

     @Override 
     protected void onPostExecute(Bundle bundle) { 
      super.onPostExecute(bundle); 
      MyFacebookTokenCache tokenCache = MyFacebookTokenCache.init(bundle); 
      doSomethingWithCache(tokenCache); 

     } 
    } 

    static class MyFacebookTokenCache extends TokenCache { 

     private Bundle mBundle; 

     public MyFacebookTokenCache(Bundle bundle) { 
      mBundle = bundle; 
     } 

     public static MyFacebookTokenCache init(Bundle bundle) { 
      return new MyFacebookTokenCache(bundle); 
     } 

     @Override 
     public Bundle load() { 
      return mBundle; 
     } 

     @Override 
     public void save(Bundle bundle) { 
      //todo 
     } 

     @Override 
     public void clear() { 
      //todo 
     } 
    } 
+0

謝謝,但Facebook使用Bundle bundle = tokenCache.load();其代碼中的任何地方。我是否需要通過在任何地方調用您的任務來替換所有這些?它的工作原理並不是我想要的。 – Emerald214

+0

誰在乎FB在哪裏使用它。 FB所擁有的TokenCache的唯一實例就是你的bundle已經初始化了。 – LuxuryMode

+0

另外,您能否向我們解釋爲什麼需要異步檢索包的神祕原因? – LuxuryMode

1

您可以使用一個回調機制。在AsyncTask中,load()完成後,調用回調方法根據返回的包執行操作。

+0

如果我這樣實現,load()函數將毫無意義。因爲TokenCache所做的工作正在加載,所以我不能像你所說的那樣將它的任務交給外部的AsyncTask。 – Emerald214

+0

好的,我明白你的意思。我已經更新了我的答案。 – TieDad

0
public static BundleAsyncTask extends AsyncTask<Void, Void, Void>{ 
    public Bundle result; 
    private final CountDownLatch latch; 
    public BundleAsyncTask(CountDownLatch latch){ 
     this.latch = latch; 
    } 

    public void doInBackground(){ 
     //get the bundle 
     latch.countDown(); 
    } 
} 

public Bundle load(){ 
    final CountDownLatch latch = new CountDownLatch(1); 
    BundleAsyncTask task = new BundleAsyncTask(latch); 
    task.execute(); 
    try{ 
     latch.await(); 
     return task.result; 
    }catch(InterruptedException e){ 
     return null; 
    } 
} 

BTW:其實我不明白你爲什麼要在這裏使用的AsyncTask。

+0

這是個笑話吧? – LuxuryMode

+0

不是一個笑話。我只是回答這個問題,但我不知道爲什麼在這裏使用'AsyncTask'。如果你想使用'AsyncTask'(我的意思是機制),我認爲這是唯一的方法。 – Ponyets