安卓 线程

安卓 线程

一、简述

      记--安卓编程中线程的简单使用例子。使用匿名方式、继承方式创建线程。

      代码文件:链接: https://pan.baidu.com/s/10saeJ5XxDOpWokn9vB6Y1w 提取码: pkfu

二、方式1--匿名类

        

        // 开启子线程
        new Thread(){
           @Override
     	   public void run(){

     		    //子线程执行的动作,比如执行test()函数
                test();
     	   }  
        }.start(); 

例子: 有一个int类型的成员num,子线程每隔一秒将num加2,点击主线程中的按钮将num的当前值显示到TextView。

        代码结构

             

        布局:

         2.2 效果

                                       

             注:TextView控件没有立即更新,需要手动更新,所以看到本来是每隔1秒追加打印num的值变为"一股脑"更新了。

        源码文件

                 MainActivity.java文件

package com.example.testthread;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

	private int num = 1;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
     // 开启子线程
        new Thread()
        {
        	@Override
        	public void run()
        	{
        		//子线程要执行的动作,每隔1秒就将num+2
        		while(true)
        		{
        			num += 2;
        			Sleep(1000);//延时1秒
        		}
        	}
        	
        }.start();
        Toast.makeText(this, "子线程1创建完毕!", Toast.LENGTH_SHORT).show();
    }

    public void on_btn_main_thread_Clicked(View v)
    {
    	Toast.makeText(this, "主线程!", Toast.LENGTH_SHORT).show();
    	TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    	for(int i=0; i<20; i++)
    	{
    		tv.append("num="+num+"\n");
    		Sleep(500);
    	}
    }
    
   public void Sleep(long ms)
   {
	   try {
			Thread.sleep(ms);//延时ms毫秒
	   } catch (InterruptedException e) {
	// TODO Auto-generated catch block
			e.printStackTrace();
		}
   }
}

三、方式2--自定义类继承Thread类

       方式1的匿名类方式虽然操作"简单",但是难以"控制",比如没有一个实际的操作对象,就不方便在后面进行对子线程的控制,如对子线程的休眠、停止、销毁等操作。还有就是匿名方式不方便"重用"。

      自定义一个类继承Thread类,并重写run方法

public class MyThread extends Thread {  
    @Override
    public void run(){  
        //要执行的动作
    }  
} 

创建子线程并启动 

new MyThread().start();//开启子线程,执行run()方法

或

MyThread thread1 = new MyThread();
thread1.start();

例子: 有一个int类型的成员num,子线程每隔一秒将num加2,点击主线程中的按钮将num的当前值显示到TextView。

代码结构

效果:

                                    

源码文件

                 MainActivity.java文件

package com.example.testthread;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

	private int num = 1;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
     // 开启子线程
     new Mythread().start();   
     Toast.makeText(this, "子线程1创建完毕!", Toast.LENGTH_SHORT).show();
    }

    public void on_btn_main_thread_Clicked(View v)
    {
    	Toast.makeText(this, "主线程!", Toast.LENGTH_SHORT).show();
    	TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    	for(int i=0; i<20; i++)
    	{
    		tv.append("num="+num+"\n");
    		Sleep(500);
    	}
    }
    
    public class Mythread extends Thread
    {
        	@Override
        	public void run()
        	{
        		//子线程要执行的动作,每隔1秒就将num+2
        		while(true)
        		{
        			num += 2;
        			Sleep(1000);//延时1秒
        		}
        	}
    }
    
   public void Sleep(long ms)
   {
	   try {
			Thread.sleep(ms);//延时ms毫秒
	   } catch (InterruptedException e) {
	// TODO Auto-generated catch block
			e.printStackTrace();
		}
   }
}

四、问题总结

1、子线程更新UI(控件)问题。

        测试代码1:在子线程中成功改变TextView控件的文本。

package com.example.testthread;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;

public class MainActivity extends Activity {

	private int num = 1;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
       // 开启子线程
        new Thread()
        {
        	@Override
        	public void run()
        	{
        		//子线程要执行的动作
    			TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    			tv.setText("子线程正在运行。。。");
        	}
        	
        }.start();
        Toast.makeText(this, "子线程1创建完毕!", Toast.LENGTH_SHORT).show();
    }

    public void on_btn_main_thread_Clicked(View v)
    {
    	Toast.makeText(this, "主线程!num="+num, Toast.LENGTH_SHORT).show();
    }
    
    public void Sleep(long ms)
    {
 	   try {
 			Thread.sleep(ms);//延时ms毫秒
 	   } catch (InterruptedException e) {
 	// TODO Auto-generated catch block
 			e.printStackTrace();
 		}
    }
}

运行结果:

                            

 测试代码2:在测试代码1的基础上修改"子线程执行的动作"部分,成功运行。

                //子线程要执行的动作
    			TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    			tv.setText("子线程正在运行");
    			num += 2;
    			Sleep(1000);

运行结果:

                                 

测试代码3:在测试代码2的基础上修改"子线程执行的动作"部分,延时1秒,二次更改TextView控件的文本,程序崩溃。

                //子线程要执行的动作
    			TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    			tv.setText("子线程正在运行");
    			num += 2;
    			Sleep(1000);
    			tv.setText("num="+num);

运行结果:

                                                  

2、如何手动立即更新UI?

      在方式1--匿名类中的按钮单击响应代码效果,并没有立即改变TextView控件

    public void on_btn_main_thread_Clicked(View v)
    {
    	Toast.makeText(this, "主线程!", Toast.LENGTH_SHORT).show();
    	TextView tv = (TextView)findViewById(R.id.tv_main_thread);
    	for(int i=0; i<20; i++)
    	{
    		tv.append("num="+num+"\n");
    		Sleep(500);
    	}
    }

使用Handler更新UI,只需在需要的时候发送一个信号。(有点像Handler是一个独立线程,收到一个信号就进行动作)

例子:子线程每隔1秒发送一个信号给handler,通知handler改变TextView的文本。主线程能够随时的打印num的值。

测试代码:

package com.example.testthread;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private int num;
	private TextView tv;
    private Handler handler = new Handler(){
		@Override
        public void handleMessage(Message msg){
			switch(msg.what){
				case 0:
						tv.setText(num+"");//改变TextView控件的文本
				default:
					break;
			}
        }
	};
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        num = 1;
        tv = (TextView)findViewById(R.id.tv_main_thread);//拿到TextView对象
        
        //开启子线程
        new Thread()
        {
        	@Override
        	public void run()
        	{
        		while(true)//每隔1秒发送一个0信号给handler
        		{
        			handler.sendEmptyMessage(0);//发送一个0信号给handler,通知handler更新UI
        			num++;
        			Sleep(1000);//延时1秒
        		}
        	}
       	
        }.start();
        
        Toast.makeText(this, "子线程1创建完毕!", Toast.LENGTH_SHORT).show();
    }

    public void on_btn_main_thread_Clicked(View v)
    {
    	Toast.makeText(this, "主线程!num="+num, Toast.LENGTH_SHORT).show();
    	
    }
    
    public void Sleep(long ms)
    {
 	   try {
 			Thread.sleep(ms);//延时ms毫秒
 	   } catch (InterruptedException e) {
 			e.printStackTrace();
 		}
    }

}

运行结果:

                         

其中发送信号给Handler:
      handler.sendEmptyMessageDelayed(0, 1000);//1秒后发送0信号。
      handler.sendEmptyMessage(0);//发送0信号

猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/82999294