国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Otto: No more callbacks

elisa.yang / 584人閱讀

摘要:他們之間除了都用了和這兩個(gè)類以及用來傳遞事件的類,再?zèng)]有其他共同的東西。當(dāng)事件多了起來,的優(yōu)勢就會(huì)非常明顯,增加的只是這些輕量級的而已。

傳統(tǒng)的方式

你要做一個(gè)todo app,有一個(gè)Activity里面有一個(gè)ListView顯示你所有的task,你的數(shù)據(jù)存儲(chǔ)在服務(wù)器。假設(shè)你沒采用任何的軟件架構(gòu)(MVC、MVP、MVVM等等),每次app打開的時(shí)候,你從服務(wù)器把數(shù)據(jù)load下來,load完了以后,通過callback把數(shù)據(jù)傳給Activity,然后顯示到listview里面。代碼結(jié)構(gòu)大概是這個(gè)樣子

public class TasksActivity extends Activity {
    private ListView mListView;
    //...
    private void loadTasks() {
        TaskModel model = new TaskModel();
        model.setTaskCallback(new TaskCallback() {
            public void onError(String msg, int code) {
                // handle error
            }
            
            public void onSucceed(List tasks) {
                updateTaskList(tasks);
            }
        });
        model.loadTasks();
    }
    
    private void updateTaskList(List tasks) {
        //Update the task list view
    }
    // other code
}

public class Task {
    // title, label, ..., and their getters and setters.
}

public class TaskModel {
    public void loadTasks() {
        //load tasks from server, when result returns, check if callback is not null and call callback
    }
    
    private TaskCallback mTaskCallback;
    public void setTaskCallback(TaskCallback callback) {
        this.mTaskCallback = callback;
    }
    
    public static interface TaskCallback {
        public void onError(String errorMsg, int code);
        public void onSucceed(List tasks);
    }
}

在這里,當(dāng)TaskModel load完了task以后,你用的是callback來通知Activity,task已經(jīng)load好了。這種callback的方式是java里面非常傳統(tǒng)的方式,尤其是涉及到異步的時(shí)候。這種方式雖然能work,但卻是非常麻煩,也非常丑陋的方式。
首先,你要定義Callback接口,然后在用的地方實(shí)現(xiàn)這個(gè)接口。
再次,你要在你的model里面申明一個(gè)callback的成員變量,在用的時(shí)候,還要判斷一下成員變量是不是空的。當(dāng)然你可以用NullObject 模式,但這也需要額外的工作。
最后,當(dāng)你發(fā)現(xiàn)定義的callback接口要變的時(shí)候,你要改動(dòng)的地方可能非常大,因?yàn)槟憧赡苡泻芏嗟牡胤綄?shí)現(xiàn)了這個(gè)接口,這是非常煩人也是非常容易出錯(cuò)的工作。
這一來二去,當(dāng)你的model比較多的時(shí)候,你會(huì)變得非常煩,這完全就是體力勞動(dòng)??!
那有沒有更好地方式來解決這個(gè)問題呢?你可能會(huì)想到是Handler或者是BroadcastReceiver,然而他們也不是很好用的東西,都要定義一些東西,判斷message,判斷action,傳遞一些引用等等。

Otto的方式

這里介紹一個(gè)library叫Otto,這是Square這個(gè)公司的一個(gè)開源項(xiàng)目,它是一個(gè)EventBus的library。簡單的來說,它類似于定義了一套Observer Pattern的便捷的實(shí)現(xiàn)方式。你在某一個(gè)地方使用@Subscribe 表示你要處理某一種事件,在某個(gè)地方用post發(fā)布這一種事件,那么前面用@Subscribe修飾的方法就可以自動(dòng)得到調(diào)用。不用定義接口,不用實(shí)現(xiàn)接口,一切都很直觀,如你所愿。
關(guān)于Otto的使用官網(wǎng)說的非常清楚。
在這里簡單地用Otto重寫一下上面的代碼,讓大家感受一下。

public class TasksActivity extends Activity {
    private ListView mListView;
    public void onCreate() {
        OttoHelper.register(this); //對于Subscriber來說,register和unregister是有必要的
    }
    //...
    private void loadTasks() {
        new TaskModel().loadTasks();
    }
    
    // 用@Subscribe 來表示用這個(gè)方法處理某種事件,這種事件就是你的方法的參數(shù)。
    // 此外,public void是必須的,方法名可以自己隨便取
     @Subscribe
    public void onTaskLoaded(TaskLoadedEvent event) {
        List tasks = event.tasks;
        // Update the task list view
    }
    
    @Subscribe
    public void onTaskLoadError(TaskLoadErrorEvent event) {
        //handler error
    }
    
    public void onDestroy() {
        OttoHelper.unregister(this)
    }
}

public class Task {
    // title, label, ..., and their getters and setters.
}

public class TaskModel {
    public void loadTasks() {
        // Load task from server
        OttoHelper.post(new TaskLoadedEvent(tasks)); //If load succeed
        OttoHelper.post(new TaskLoadErrorEvent(errorMsg, code); //If load error
    }
}

//Bus 一般是用作單例的,所以有一個(gè)helper會(huì)很方便
public class OttoHelper {
    private static final Bus sBusInstance = new Bus();
    public void static register(Object obj) {
        sBusInstance.register(obj);
    }
    
    public void static unregister(Object obj) {
        sBusInstance.register(obj);
    }
    
    public static void post(Object event) {
        sBusInstance.post(event);
    }
    
}

public class TaskLoadedEvent {
    public final List tasks;
    public TaskLoadedEvent(List tasks) {
        this.tasks = tasks;
    }
}

public class TaskLoadErrorEvent {
    //final field errorMsg and code, and construction, just like TaskLoadedEvent
}

需要說明的是,這里只處理了一種事件(load task),所以O(shè)tto的優(yōu)勢還不是很明顯,然而你依然可以明顯感受到的是,TaskModelTasksActivity之間的耦合性更弱了。他們之間除了都用了TaskOttoHelper這兩個(gè)類以及用來傳遞事件的Event類,再?zèng)]有其他共同的東西。

當(dāng)事件多了起來,Otto的優(yōu)勢就會(huì)非常明顯,增加的只是Event這些輕量級的POJO而已。
非常需要的一點(diǎn)是,最好每一種事件都使用特殊的Event類,千萬不要使用常見的類,比如String等等,更不要使用Object,因?yàn)镺tto判斷Subscribe方法所處理的事件是通過方法的參數(shù)來判斷的。只要 instance of為true,那么這個(gè)方法就會(huì)得到調(diào)用。舉個(gè)例子,在上面的TasksActivity里,假如你有另外一個(gè)Subscribe函數(shù),它的參數(shù)是Object:

public class TasksActivity extends Activity {
    //...
    @Subscribe
    public void onTaskLoaded(TaskLoadedEvent event) {
        List tasks = event.tasks;
        // Update the task list view
    }
    
    @Subscribe
    public void onTaskLoadError(TaskLoadErrorEvent event) {
        //handler error
    }
    
    @Subscribe
    public void onSomeEvent(Object event) {
        //handle some-event
    }
}

在上面的事件中,bus post的任何事件,主要TasksActivity沒有unregister,那么onSomeEvent就會(huì)得到調(diào)用,比如task load成功了,你post了TaskLoadedEvent,那么除了onTaskLoaded會(huì)得到調(diào)用的之外,onSomeEvent也會(huì)得到調(diào)用,這很可能不是你想要的。
我曾經(jīng)就犯了這個(gè)愚蠢的錯(cuò)誤,更搞笑的是,我在onSomeEvent里面直接finish activity了,結(jié)果每一次別的事件過來,Activity就退出了,我以為程序奔潰了,找了半天都找不出原因,因?yàn)槟阏inish activity是不會(huì)有error log的,最后終于懷疑到它頭上來,然后才解決了這個(gè)問題。
compile "com.squareup:otto:1.3.7’加到你的dependencies里面,試用以下,我敢打賭,你再也不會(huì)定義callback了,Callbacks should be dead!.
當(dāng)然,除了Otto,還有其他的一些library,比如greenbot開源的EventBus,功能貌似比Otto更強(qiáng),但是我個(gè)人選擇Otto,因?yàn)樾叛鯯quare,哈哈。。

Disclaimer

這個(gè)例子只是用來說明Otto相對于callback的好處,對于一個(gè)正常的類似于上面的例子的app,這篇文章中提到的model和activity的交互方式并不是最好的方式,有其他更好的比如Functional Reactive Programming(RxJava)。同時(shí),我們應(yīng)該使用MVP模式,把Activity當(dāng)做View,而不是直接在里面調(diào)用model。

如果有任何意見或建議,或者是發(fā)現(xiàn)文中有任何問題歡迎留言!

作者 小創(chuàng) 更多文章 | Github | 公眾號

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/64357.html

相關(guān)文章

  • Android干貨框架集錦,搭建項(xiàng)目必不可少

    摘要:最佳解析最佳解析最佳解析是一個(gè)依賴注入框架,由谷歌開發(fā),最早的版本由公司開發(fā)。在對的介紹中指出,即,這里的即數(shù)據(jù)結(jié)構(gòu)中的有向無環(huán)圖。也就是說,是一個(gè)基于有向無環(huán)圖結(jié)構(gòu)的依賴注入庫,因此的使用過程中不能出現(xiàn)循環(huán)依賴。 在開發(fā)過程中使用過很多優(yōu)秀框架,比如網(wǎng)絡(luò)的okhttp,圖片的Fresco,注入的Gagger2等,都是非常優(yōu)秀的框架。 所以今天在此介紹下至今本人知道的一些比較流行主流且...

    zhisheng 評論0 收藏0
  • 淺析Otto框架,并與EventBus對比

    摘要:它有發(fā)布者,訂閱者這兩個(gè)主要對象。的最佳實(shí)踐就是通過反射犧牲了微小的性能,同時(shí)極大的降低了程序的耦合度。官網(wǎng)和應(yīng)用場景框架的主要功能是幫助我們來降低多個(gè)組件通信之間的耦合度的解耦。 前兩天在公眾號里發(fā)了一篇有關(guān)EventBus的文章《玩轉(zhuǎn)EventBus,詳解其使用》,有讀者和開發(fā)者反饋說沒有OTTO好用。確實(shí)是,各有優(yōu)缺點(diǎn)吧,那今天就有必要再講一下Otto事件框架。 OTTO是Squ...

    EsgynChina 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<