天天看點

android異步操作

為了使ui在資料擷取時不僵死,資料擷取需要在新開worker線程中進行,然後将傳回結果在ui線程中進行讀取并渲染頁面。面對這種異步處理,到底如何寫才簡潔,先後面臨過三種實作方式。

首先是最原始的java方式,new 一個thread出來,将處理runnable進去執行,執行完之後通過handler post到ui線程去更新界面。然後發現1.5後有了asynctask,非常好用,以後的項目中全部改成衍生出一個asynctask的子類,類中自然定義了運作前方法、運作中方法和運作後在ui中運作的方法。目前我做的項目中對asynctask做了封裝,把它從原本的子類編寫的過程,改成了函數調用方式,這就是目前正使用的第三種方法。

android異步操作

一個android應用中,activity通常可以建立以上層次關系。然後,在baseactivity中對asynctask進行了封裝,形成doasync方法。方法體内建立一個新的asynctask并執行,由于asynctask是泛型參數,doasync方法中傳入的接口的參數也對應使用了泛型。至此,一個典型的異步調用的案例如下:

this.doasync(new callable<string>() {  

            // 希望異步加載的資料  

            public string call() throws exception {  

                string resu = networktool.httpgeturl(  

                             "http://www.baidu.com", "gbk");  

                return resu;  

            }  

        }, new callback<string>() {  

            // 當加載完成後回調,在ui線程中的操作  

            public void oncallback(final string resu) {  

                if (null != resu) {  

                    tv_text1.settext(getrt().text1 + resu);  

                } else {  

                    tools.showneterr(homeactivity.this);  

                }  

        });  

這樣,就從本來繼承asynctask建立一個子類,然後初始化,然後運作的開發過程轉變為了函數調用的過程。可以看到,調用可是簡潔了很多!

為了實作它,我們附上baseactivity中如下封裝代碼,需要說明的是這不是我的原創,我借鑒于andengine引擎的實作代碼進行的修改。

附源碼:

public class activityutils {  

    public static <t> void doasync(final context pcontext, final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback) {  

        activityutils.doasync(pcontext, ptitleresid, pmessageresid, pcallable, pcallback, null, false);  

    }  

    public static <t> void doasync(final context pcontext, final charsequence ptitle, final charsequence pmessage, final callable<t> pcallable, final callback<t> pcallback) {  

        activityutils.doasync(pcontext, ptitle, pmessage, pcallable, pcallback, null, false);  

    public static <t> void doasync(final context pcontext, final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback, final boolean pcancelable) {  

        activityutils.doasync(pcontext, ptitleresid, pmessageresid, pcallable, pcallback, null, pcancelable);  

    public static <t> void doasync(final context pcontext, final charsequence ptitle, final charsequence pmessage, final callable<t> pcallable, final callback<t> pcallback, final boolean pcancelable) {  

        activityutils.doasync(pcontext, ptitle, pmessage, pcallable, pcallback, null, pcancelable);  

    public static <t> void doasync(final context pcontext, final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        activityutils.doasync(pcontext, ptitleresid, pmessageresid, pcallable, pcallback, pexceptioncallback, false);  

    public static <t> void doasync(final context pcontext, final charsequence ptitle, final charsequence pmessage, final callable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        activityutils.doasync(pcontext, ptitle, pmessage, pcallable, pcallback, pexceptioncallback, false);  

    public static <t> void doasync(final context pcontext, final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback, final boolean pcancelable) {  

        activityutils.doasync(pcontext, pcontext.getstring(ptitleresid), pcontext.getstring(pmessageresid), pcallable, pcallback, pexceptioncallback, pcancelable);  

    public static <t> void doasync(final context pcontext, final charsequence ptitle, final charsequence pmessage, final callable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback, final boolean pcancelable) {  

        new asynctask<void, void, t>() {  

            private progressdialog mpd;  

            private exception mexception = null;  

            @override  

            public void onpreexecute() {  

                this.mpd = progressdialog.show(pcontext, ptitle, pmessage, true, pcancelable);  

                if(pcancelable) {  

                    this.mpd.setoncancellistener(new oncancellistener() {  

                        @override  

                        public void oncancel(final dialoginterface pdialoginterface) {  

                            pexceptioncallback.oncallback(new cancelledexception());  

                            pdialoginterface.dismiss();  

                        }  

                    });  

                super.onpreexecute();  

            public t doinbackground(final void... params) {  

                try {  

                    return pcallable.call();  

                } catch (final exception e) {  

                    this.mexception = e;  

                return null;  

            public void onpostexecute(final t result) {  

                    this.mpd.dismiss();  

                    log.e("error", e.tostring());  

                if(this.iscancelled()) {  

                    this.mexception = new cancelledexception();  

                if(this.mexception == null) {  

                    pcallback.oncallback(result);  

                    if(pexceptioncallback == null) {  

                        if (this.mexception != null)  

                            log.e("error", this.mexception.tostring());  

                    } else {  

                        pexceptioncallback.oncallback(this.mexception);  

                    }  

                super.onpostexecute(result);  

        }.execute((void[]) null);  

    public static <t> void doprogressasync(final context pcontext, final int ptitleresid, final progresscallable<t> pcallable, final callback<t> pcallback) {  

        activityutils.doprogressasync(pcontext, ptitleresid, pcallable, pcallback, null);  

    public static <t> void doprogressasync(final context pcontext, final int ptitleresid, final progresscallable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        new asynctask<void, integer, t>() {  

                this.mpd = new progressdialog(pcontext);  

                this.mpd.settitle(ptitleresid);  

                this.mpd.seticon(android.r.drawable.ic_menu_save);  

                this.mpd.setindeterminate(false);  

                this.mpd.setprogressstyle(progressdialog.style_horizontal);  

                this.mpd.show();  

                    return pcallable.call(new iprogresslistener() {  

                        public void onprogresschanged(final int pprogress) {  

                            onprogressupdate(pprogress);  

            public void onprogressupdate(final integer... values) {  

                this.mpd.setprogress(values[0]);  

                    log.e("error", e.getlocalizedmessage());  

                    /* nothing. */  

                        log.e("error", this.mexception.getlocalizedmessage());  

    public static <t> void doasync(final context pcontext, final int ptitleresid, final int pmessageresid, final asynccallable<t> pasynccallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        final progressdialog pd = progressdialog.show(pcontext, pcontext.getstring(ptitleresid), pcontext.getstring(pmessageresid));  

        pasynccallable.call(new callback<t>() {  

            public void oncallback(final t result) {  

                    pd.dismiss();  

                pcallback.oncallback(result);  

        }, pexceptioncallback);  

    public static class cancelledexception extends exception {  

        private static final long serialversionuid = -78123211381435595l;  

}  

public interface asynccallable<t> {  

    // ===========================================================  

    // final fields  

    // methods  

    /** 

     * computes a result asynchronously, return values and exceptions are to be handled through the callbacks. 

     * this method is expected to return almost immediately, after starting a {@link thread} or similar. 

     * 

     * @return computed result 

     * @throws exception if unable to compute a result 

     */  

    public void call(final callback<t> pcallback, final callback<exception> pexceptioncallback);  

public interface callback<t> {  

     * 當加載完成後回調,加載完畢的事後處理   

    public void oncallback(final t pcallbackvalue);  

public interface iprogresslistener {  

    // constants  

     * @param pprogress between 0 and 100. 

    public void onprogresschanged(final int pprogress);  

public class baseactivity extends activity {  

     *  

     * @param <t> 模闆參數,操作時要傳回的内容 

     * @param pcallable 需要異步調用的操作 

     * @param pcallback 回調 

    protected <t> void doasync(final callable<t> pcallable, final callback<t> pcallback) {  

        activityutils.doasync(this, null, "内容讀取中,請稍等...", pcallable, pcallback, null, false);  

    protected <t> void doasync(final charsequence ptitle, final charsequence pmessage, final callable<t> pcallable, final callback<t> pcallback) {  

        activityutils.doasync(this, ptitle, pmessage, pcallable, pcallback, null, false);  

     * performs a task in the background, showing a {@link progressdialog}, 

     * while the {@link callable} is being processed. 

     * @param <t> 

     * @param ptitleresid 

     * @param pmessageresid 

     * @param perrormessageresid 

     * @param pcallable 

     * @param pcallback 

    protected <t> void doasync(final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback) {  

        this.doasync(ptitleresid, pmessageresid, pcallable, pcallback, null);  

     * performs a task in the background, showing a indeterminate {@link progressdialog}, 

     * @param pexceptioncallback 

    protected <t> void doasync(final int ptitleresid, final int pmessageresid, final callable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        activityutils.doasync(this, ptitleresid, pmessageresid, pcallable, pcallback, pexceptioncallback);  

     * performs a task in the background, showing a {@link progressdialog} with an progressbar, 

     * while the {@link asynccallable} is being processed. 

     * @param pasynccallable 

    protected <t> void doprogressasync(final int ptitleresid, final progresscallable<t> pcallable, final callback<t> pcallback) {  

        this.doprogressasync(ptitleresid, pcallable, pcallback, null);  

     * performs a task in the background, showing a {@link progressdialog} with a progressbar, 

    protected <t> void doprogressasync(final int ptitleresid, final progresscallable<t> pcallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        activityutils.doprogressasync(this, ptitleresid, pcallable, pcallback, pexceptioncallback);  

     * performs a task in the background, showing an indeterminate {@link progressdialog}, 

    protected <t> void doasync(final int ptitleresid, final int pmessageresid, final asynccallable<t> pasynccallable, final callback<t> pcallback, final callback<exception> pexceptioncallback) {  

        activityutils.doasync(this, ptitleresid, pmessageresid, pasynccallable, pcallback, pexceptioncallback);  

繼續閱讀