[初试Android]Service+跨线程操作GUI的一个小例子

1 篇文章 0 订阅
1 篇文章 0 订阅

[初试Android]Service+跨线程操作GUI的一个小例子

1、实验内容       

        本例子练习使用Service以及控件的跨线程操作:主Activity界面用来启动、停止一个服务,该服务启动后会产生一个线程,该线程每隔一秒产生一个随机双精度数,并将该随机数显示在主Activity界面的一个TextView控件中。

2、实现过程

2.1 建立工程

       首先建立一个空白的Android工程:工程名为ServiceDemo,程序包存储为per.elton.servicedemo,主Activity为默认名MainActivity。

2.2 添加Service实现类

       在per.elton.servicedemo下新建一个Service实现类:RandomService,该类继承android.app.Service。并重载该类的三个方法:

public class RandomService extends Service {
	// 服务启动时调用一次
	@Override
	public void onCreate(){}

	// 服务每次启动都调用一次
	@Override
	public void onStart(Intent intent, int startID){}

	// 停止服务时调用
	@Override
	public void onDestory(){}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}
}

2.3 布置MainActivity界面

      添加两个按钮分别用来启动(btnStartService)和停止服务(btnStopService),添加一个TextView(tvShowRandom)用来显示随机数。布局如下图所示:

Fig 1

2.4 添加事件监听

       使MainActivity实现android.view.OnClickListener接口,并添加该接口的实现方法: 

	@Override
	public void onClick(View v) {}

      对于“Start Service”按钮和“Stop Service”:添加对按钮点击事件的处理为如下代码。

	@Override
	public void onClick(View v) {
		Intent intent = new Intent(this,RandomService.class);
		switch (v.getId()) {
		case R.id.btnStartService:
			// 显示启动服务,知道服务的类以及路径
			startService(intent);
			// 隐式启动服务,不清楚类的更详细细节
			/*
			 * Intent intentHiden = new Intent();
			 * intentHiden.setAction("MY_RANDOM_SERVICE");
			 * startService(intentHiden);
			*/
			break;

		case R.id.btnStopService:
			stopService(intent);
			break;
		}		
	}

      既可以显式启动服务,也可以通过服务在AndroidManifest.xml中的名字(本例服务的名字名为“MY_RANDOM_SERVICE”)来启动服务。服务在XML文件中的设置如下:

        <service android:name="RandomService">
            <intent-filter>
                <action android:name="MY_RANDOM_SERVICE"/>
            </intent-filter>
        </service>

      本例中采用直接指定服务的实现类来启动RandomService这个服务。
      在Activity启动时,将事件响应注册到两个按钮上。在onCreate方法中添加如下事件监听器。

         Button btnStartService = (Button)findViewById(R.id.btnStartService);
        Button btnStopService = (Button)findViewById(R.id.btnStopService);
        btnStartService.setOnClickListener(this);
        btnStopService.setOnClickListener(this);

2.5 添加updateGUI方法

      为了实现RandomService服务所启动的线程对MainActivity中tvShowRandom控件的操作,在MainAcitivity中添加一个静态的方法updateGUI(double),以方便服务中线程的调用。

	private static TextView tvRandom; 	// 在onCreate方法中完成赋值
	private static double dbRandom;	// 服务传递过来的随机数
	private static int intIndex=0;	// 记录产生的随机数的次数
	private static Handler handler = new Handler();	// 接受子线程传递来的数据,并更新UI

	private static Runnable refreshRunnable = new Runnable() {		
		@Override
		public void run() {
			tvRandom.setText(String.valueOf(intIndex++)+" 产生的随机数:"+String.valueOf(dbRandom));
		}
	};

    	public static void updateGUI(double dbTmp){
    		dbRandom = dbTmp;
    		handler.post(refreshRunnable);
    	}

      关于Handler的更多介绍,http://www.pin5i.com/showtopic-android-handler.html。由于updateGUI方法是静态的,所以该方法涉及到的相关变量也都为静态的。
      至此,只要RandomService服务通过调用静态方法updateGUI即可更新主界面的空间内容,也就是显示一个随机数。接下来实现RandomService。

2.6 实现RandomService中的关键方法

      RandomServie需要实现2.2中所列出的三个主要方法:onCreate,onStart和onDestory。分别用来在初始化服务阶段、启动服务阶段和注销服务阶段调用。在onCreate方法中需要初始化一个线程,并通过一个Runnable变量指定其要实现的功能。相关代码如下:

	private Thread rsThread;
	
	private Runnable runableWork = new Runnable() {
		public void run() {
			try{
				while(!Thread.interrupted()){
					double dbRandom = Math.random();
					MainActivity.updateGUI(dbRandom);// 更新界面
					Thread.sleep(1000);	     // 子线程休眠一秒钟	
				}
			}
			catch (Exception e) {
				Log.i("RANDOM_SERVICE", "Exception found ... ...");
			}
		}
	};
	
	@Override
	public void onCreate(){
		super.onCreate();
		Toast.makeText(this, "Random service has been created now ... ...", Toast.LENGTH_LONG).show();
		
		// 初始化线程
		rsThread = new Thread(null,runableWork,"rsThread");
	}


      服务的onStart方法在每次RandomService恢复运行或者启动时调用此方法,因此可在此方法中启动子线程,代码如下:

	@Override
	public void onStart(Intent intent, int startID){
		super.onStart(intent, startID);
		Toast.makeText(this, "Random service starts ... ...", Toast.LENGTH_LONG).show();
		
		// 启动线程产生并显示随机数
		if (!rsThread.isAlive()){
			rsThread.start();
		}
	}

       停止RandomService服务:

	@Override
	public void onDestroy(){
		super.onDestroy();
		Toast.makeText(this, "Random service has been destroied now ... ...", Toast.LENGTH_LONG).show();
		
		rsThread.interrupt();
	}

      现在所有的编码就完成了,可以直接编译放到机器上运行。本例中,模拟机采用的系统是基于android2.3.3平台的。

3、代码部分以及运行

      代码在第二章节已有较详细的介绍,此处将所有的代码打包,点击下载

      运行界面如下所示:

 

Fig 2

4、总结

      本例主要是练习如何实现一个服务,以及如何在子线程中操作主线程的GUI。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值