閱讀865 返回首頁    go 阿裏雲 go 技術社區[雲棲]


有關Android中Service實現UI更新(Binder的運用)

我們知道Android的程序架構本身即是遵循MVC模式設計的,將顯示和邏輯操作進行了很好的分離。xml文件進行view的添加和布局,Activity來實現各種View的展示,而service實現將數據按一定邏輯在View中顯示。基於這樣的原則我們設計程序時,就需要做到讓他們各司其職,合理搭配,如此才能使我們設計的Android程序更高效,更安全以及易於維護,當然這是一個很大很大很大的話題,此處我隻對service和Activity的職責進行簡單闡述,希望能起到拋磚引玉的作用,當然若內容如有雷同不勝榮幸.

    Service是在Android程序後台運行的組件,比如音樂播放,網絡下載等,這些操作的確都可以在service中完成,但並不是說我們隻可以再service中完成,在Activity中一樣可以實現,那為什麼我們還要一個service呢,曾經我也疑惑過,後來我知道了在Android中又五個進程等級(1.Foreground Process: 2.Visible Process 3.ServiceProcess4.Background Process 5.Empty Procecc)在係統內存資源不夠的時候,係統會首先將等級較低的進程殺死來滿足其他高等級的進程正常運行,而service正處於第三等級,而被覆蓋住的Activiy處於第四等級,這樣當我們在運行程序時因為某種原因而將當前Activity覆蓋,那我們在該Activity中的很多操作尤其需要網絡交互的很可能會因為係統內存資源不足,而將其殺掉。這樣就會導致數據的不完成,使程序的魯棒性不夠強,而如果將他們都放在service中實現那就穩妥多了,程序也相對穩定多了。當然程序的穩定性是由很多因素構成的,這隻是其中之一而已。那好,既然說放在service中操作,那就在那兒操作吧,這不就完了嗎,可是就在我們準備這樣做時,總會意識到一個問題,當我們把這些操作統統放到service中實現時,那Activity的中控件的更新怎麼辦,比如因為播放總會有進度條的,文件下載也是要時時更新下載量的,不知道各位怎麼處理這個問題的,我在網上查了查,看到的方法都是通過廣播,即在 Activity中注冊一個廣播,然後通過廣播進行service和Activity間的數據傳遞,同時以達到更新UI的目的,雖然我沒這麼做過,但我知道這是可以的,但我總覺的,這樣有點勞師動眾了,而且我曾經用了一次廣播,根據我的使用的效果來說覺得廣播不適合做一些時時更新的操作(具體原因我沒有深入研究過,不敢過多評論),反應不夠及時。所以我自己就試著用別的方法進行UI更新,最後我覺得通過Binder對象實現,怎麼實現我就不用文字說明了,下麵我就隨便寫了個例子簡單說明。拋磚引玉吧

用來更新UI的service

package com.gqs.service;
 
 import android.app.Service;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.widget.TextView;
 
 public class UpdateService extends Service {
     private int data;
     private Handler handler;
 
     @Override
     public IBinder onBind(Intent intent) {
         // TODO Auto-generated method stub
         return new MyBinder();
     }
 
     public class MyBinder extends Binder {
         public void setDate(final TextView tv, final UpdateData updata) {
             new Thread(new MyThread()).start();
             handler = new Handler() {
                 public void handleMessage(Message msg) {
                     updata.update(tv, data);
                 }
             };
         }
     }
 
     public class MyThread implements Runnable {
 
         @Override
         public void run() {
             while (true) {
                 data++;
                 Message msg = handler.obtainMessage();
                 msg.arg1 = data;
                 handler.sendMessage(msg);
                 try {
                     Thread.sleep(1000);
                 } catch (InterruptedException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 }
             }
         }
 
     }
 
     public interface UpdateData {
         public void update(TextView tv, int data);
 
     }
 }

package com.gqs.activity;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.gqs.service.UpdateService;
import com.gqs.service.UpdateService.MyBinder;
import com.gqs.service.UpdateService.UpdateData;


public class ServiceToActivityActivity extends Activity {
    /** Called when the activity is first created. */
    private TextView tv;
    private UpdateService.MyBinder binder;
    private Button btnStart;
    private ServiceConnection conn=new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            binder=(MyBinder) service;
            tv.setText("已連接");
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btnStart=(Button)findViewById(R.id.btnStart);
        tv=(TextView)findViewById(R.id.textView);
        Intent intent=new Intent(this,UpdateService.class);
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
        btnStart.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if(binder!=null)
                {
                    binder.setDate(tv, new UpdateData() {
                        
                        @Override
                        public void update(TextView tv, int data) {
                            // TODO Auto-generated method stub
                            tv.setText(data+"");
                        }
                    });
                }
                else
                {
                    Toast.makeText(getApplicationContext(), "連接失敗", 1).show();
                }
            }
        });
    }
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        unbindService(conn);
        super.onDestroy();
    }
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:andro
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:
        android:text="@string/hello" />
    <Button 
        android:text="開始"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:
        />
</LinearLayout>


最後更新:2017-04-03 21:30:11

  上一篇:go 文件句柄備忘
  下一篇:go sar usage