91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

android Robospice的工作原理是什么

發布時間:2022-03-29 16:50:29 來源:億速云 閱讀:156 作者:iii 欄目:移動開發

這篇文章主要講解了“android Robospice的工作原理是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“android Robospice的工作原理是什么”吧!

一些現有的解決方案

Robospice 比起 AsyncTask 的確好太多了,但是依然存在一些問題。比如下面這段常見代碼,通過Robospice在Activity中發起一個請求的過程。你并不需要細讀,只要有個大概的概念就好:

FollowersRequest request = new FollowersRequest(user);  lastRequestCacheKey = request.createCacheKey();  spiceManager.execute(request, lastRequestCacheKey,      DurationInMillis.ONE_MINUTE,     new RequestListener<FollowerList> {       @Override       public void onRequestFailure(SpiceException e) {           // On success       }         @Override       public void onRequestSuccess(FollowerList listFollowers) {         // On failure       }     });

然后是請求的具體代碼:

public class FollowersRequest extends SpringAndroidSpiceRequest<FollowerList> {    private String user;     public FollowersRequest(String user) {     super(FollowerList.class);     this.user = user;   }     @Override   public FollowerList loadDataFromNetwork() throws Exception {     String url = format("https://api.github.com/users/%s/followers", user);     return getRestTemplate().getForObject(url, FollowerList.class);   }     public String createCacheKey() {       return "followers." + user;   } }

存在的問題

你需要為每個請求都做上述的處理,代碼會顯得很臃腫:

-  對于你的每種請求你都需要繼承SpiceRequest寫一個特定的子類。

-  同樣的,對于每種請求你都需要實現一個RequestListener來監聽。

-  如果你的緩存過期時間很短,用戶就需要花較長時間等待你的每個請求結束。

-  RequestListener持有了Activity的隱式引用,那么是不是還需要內存泄露的問題。

綜上,這并不是一個很好的解決方案。

五步,讓程序簡潔而健壯

在我開始開發Candyshop的時候,我嘗試了其他的方法。我試圖通過混合一些擁有有趣特性的庫來構造一個簡單而健壯的解決方案。這是我用到的庫的列表:

* AndroidAnnotations用來處理后臺任務,EBean等等&hellip;&hellip;

* Spring RestTemplate用來處理 REST(含狀態傳輸)的網絡請求,這個庫和AndroidAnnotations配合的非常好。

* SnappyDB這個庫主要用來將一些 Java 對象緩存到本地文件中。

* EventBus 通過 Event Bus 來解耦處理 App 內部組建間的通訊。

下圖就是我將要詳細講解的整體架構:

android Robospice的工作原理是什么

第一步 一個易于使用的緩存系統

你肯定會需要一個持久化的緩存系統,保持這個系統盡可能簡單。

@EBean public class Cache {      public static enum CacheKey { USER, CONTACTS, ... }       public <T> T get(CacheKey key, Class<T> returnType) { ... }     public void put(CacheKey key, Object value) { ... } }

第二步 一個符合REST的Client

這里我通過下面的例子來說明。記得要確保你使用 REST API 放在同一個地方。

@Rest(rootUrl = "http://anything.com") public interface CandyshopApi {       @Get("/api/contacts/")     ContactsWrapper fetchContacts();       @Get("/api/user/")     User fetchUser();   }

第三步 應用級的事件總線(Event Bus)

在程序最初的時候就初始化Event bus對象,然后應用的全局都可以訪問到這個對象。在Android中, Application初始化是一個很好的時機。

public class CandyshopApplication extends Application {      public final static EventBus BUS = new EventBus();     ... }

第四步 處理那些需要數據的Activity

對于這一類的Activity,我的處理方式和Robospice非常類似,同樣是基于Service解決。不同的是,我的Service并不是Android提供的那個,而是一個常規的單例對象。這個對象可以被App的各處訪問到,具體的代碼我們會在第五步進行講解,在這一步,我們先看看這種處理Activity代碼結構是怎么樣的。因為,這一步可以看到的是我們簡化效果***烈的部分!

@EActivity(R.layout.activity_main) public class MainActivity extends Activity {       // Inject the service     @Bean protected AppService appService;       // Once everything is loaded&hellip;     @AfterViews public void afterViews() {         // &hellip; request the user and his contacts (returns immediately)         appService.getUser();         appService.getContacts();     }       /*         The result of the previous calls will         come as events through the EventBus.         We'll probably update the UI, so we         need to use @UiThread.     */       @UiThread public void onEvent(UserFetchedEvent e) {         ...     }       @UiThread public void onEvent(ContactsFetchedEvent e) {         ...     }       // Register the activity in the event bus when it starts     @Override protected void onStart() {         super.onStart();         BUS.register(this);     }       // Unregister it when it stops     @Override protected void onStop() {         super.onStop();         BUS.unregister(this);     }   }

一行代碼完成對用戶數據的請求,同樣也只需要一行代碼來解析請求所返回的數據。對于通訊錄等其他數據也可以用一樣的方式來處理,聽起來不錯吧!

第五步單例版的后臺服務

正如我在上一步說的那樣,這里使用的Service并不是Android提供的Service類。其實,一開始的時候,我考慮使用Android提供的Services,不過***還是放棄了,原因還是為了簡化。因為 Android提供的Services通常情況下是為那些在沒有Activity展示情況下但還需要處理的操作提供服務的。另一種情況,你需要提供一些功能給其他的應用。這其實和我的需求并不完全相符,而且用單例來處理我的后臺請求可以讓我避免使用復雜的借口,譬如:ServiceConnection,Binder等等&hellip;&hellip;

這一部分可以探討的地方就多了。為了方便理解,我們從架構切入展示當Activity調用getUser()和getContacts()的時候究竟發生了什么。

你可以把下圖中每個serial當作一個線程:

android Robospice的工作原理是什么

正如你所看到的,這是我非常喜歡的模式。大部分情況下用戶不需要等待,程序的視圖會立刻被緩存數據填充。然后,當抓取到了服務端的***數據,視圖數據會被新數據替代掉。與此對應的是,你需要確保你的Activity可以接受多次同樣類型的數據。在構建Activity的時候記住這一點就沒有任何問題啦。

下面是一些示例代碼:

// As I said, a simple class, with a singleton scope @EBean(scope = EBean.Scope.Singleton) public class AppService {       // (Explained later)     public static final String NETWORK = "NETWORK";     public static final String CACHE = "CACHE";       // Inject the cache (step 1)     @Bean protected Cache cache;       // Inject the rest client (step 2)     @RestService protected CandyshopApi candyshopApi;       // This is what the activity calls, it's public     @Background(serial = CACHE)     public void getContacts() {           // Try to load the existing cache         ContactsFetchedEvent cachedResult =             cache.get(KEY_CONTACTS, ContactsFetchedEvent.class);           // If there's something in cache, send the event         if (cachedResult != null) BUS.post(cachedResult);           // Then load from server, asynchronously         getContactsAsync();     }       @Background(serial = NETWORK)     private void getContactsAsync() {           // Fetch the contacts (network access)         ContactsWrapper contacts = candyshopApi.fetchContacts();           // Create the resulting event         ContactsFetchedEvent event = new ContactsFetchedEvent(contacts);           // Store the event in cache (replace existing if any)         cache.put(KEY_CONTACTS, event);           // Post the event         BUS.post(event);       }   }

似乎每個請求之中的代碼還是有點多!實際上,這是我為了更好說明才進行了展開。不難發現,這些請求都遵守了類似的模式,所以你可以很容易的構造一個 Helper 來簡化他們。比如 getUser()可以是這樣的:

@Background(serial = CACHE) public void getUser() {     postIfPresent(KEY_USER, UserFetchedEvent.class);     getUserAsync(); }   @Background(serial = NETWORK) private void getUserAsync() {     cacheThenPost(KEY_USER, new UserFetchedEvent(candyshopApi.fetchUser())); }

那么serial是用來做什么的? 讓我們看看文檔是怎么說的:

默認情況下,所有@Background的匿名方法都是并行執行的。但是如果兩個方法使用了同樣名字的serial則會順序運行在同一個線程中,一個接著一個執行。

雖然把網絡請求放在一個線程中順序執行可能會導致性能下降,但是這使得“先POST然后GET獲得數據”的那類事務處理起來非常容易,這是個特性值得為此犧牲一些性能。退一步講,如果你真的發現性能不可接受,還是可以很容易使用多個serial來解決。現在版本的Candyshop中,我同時使用了四個不同的serial。

感謝各位的閱讀,以上就是“android Robospice的工作原理是什么”的內容了,經過本文的學習后,相信大家對android Robospice的工作原理是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

北川| 鸡泽县| 周宁县| 蕲春县| 蓬莱市| 新沂市| 偏关县| 平乐县| 咸宁市| 黑山县| 定边县| 诏安县| 应用必备| 祁东县| 辽阳县| 陆丰市| 黄山市| 赤水市| 永宁县| 海安县| 聊城市| 大余县| 沙田区| 双流县| 赫章县| 雷波县| 格尔木市| 都江堰市| 郧西县| 岳阳县| 磐石市| 河曲县| 贵德县| 公安县| 布尔津县| 盐边县| 上虞市| 出国| 周口市| 滦南县| 遂平县|