Android0909<十四>(Service、Android线程)

来源:互联网 发布:unity3d obj 文件导入 编辑:程序博客网 时间:2024/05/17 08:46

Service

利用Service做一个虚拟进度条
ProgressBar进度条,progress可以设置默认的进度
在activity_main.xml中加入进度条

 <ProgressBar        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:id="@+id/progressBar"        android:layout_gravity="center_horizontal"        android:progress="50"/>    <Button        android:id="@+id/start_download"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开始下载"/>

设置线程,通过启动服务来启动线程,线程启动进度,
MyService.java

public class MyService extends Service{    private int count;    @Nullable    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        super.onCreate();        Log.d("运行到了","onCreate");    }    @Override    public void onDestroy() {        super.onDestroy();        Log.d("运行到了","onDestroy");    }    @Override    public int onStartCommand(final Intent intent, int flags, int startId) {        Log.d("运行到了","onStartCommand");        new Thread(new Runnable() {            @Override            public void run() {                while(count<100){                    if (count>100){                        count=0;                    }                    count++;                    Intent intent1=new Intent();                    intent1.setAction(MainActivity.DOWN_LOAD_ACTION);                    intent1.putExtra("count",count);                    sendBroadcast(intent1);                    try {                        Thread.sleep(200);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();        return super.onStartCommand(intent, flags, startId);    }}

进行动态注册,在Activity_Manifest.xml中注册

 <service android:name=".MyService"></service>

在MainActivity.java中进行设置监听事件

public class MainActivity extends Activity {    private Button btn_start_service;    private Button btn_stop_service;    private Button btn_start_download;    private ProgressBar progressBar;    private MyDownLoadService mDownLoadService;    public static final String DOWN_LOAD_ACTION="com.service.text";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);             btn_start_service= (Button) findViewById(R.id.start_service);        btn_start_service.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                startService(intent);            }        });        btn_stop_service= (Button) findViewById(R.id.stop_service);        btn_stop_service.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                stopService(intent);            }        });        mDownLoadService=new MyDownLoadService();        IntentFilter filter=new IntentFilter();        filter.addAction(DOWN_LOAD_ACTION);        registerReceiver(mDownLoadService,filter);        progressBar= (ProgressBar) findViewById(R.id.progressBar);        btn_start_download= (Button) findViewById(R.id.start_download);        btn_start_download.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                startService(intent);            }        });    }    class MyDownLoadService extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            int count=intent.getIntExtra("count", 0);            progressBar.setProgress(count);        }    }    //解绑,取消广播    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(mDownLoadService);    }}

这里写图片描述

Service是运行在主线程中,第一次运行时会调用onCreate()、onStartCommand(),当第二次启动时只会调用onStartCommand(),而当只在后台允许一个耗时操作时就要用到IntentService,IntentService本身包含一个线程,包含一个消息队列,会将后续的消息排在队列中,然后等待前面的消息运行结束后,在进行处理后续的消息。

在activity_main.xml中添加一个按钮

 <Button        android:id="@+id/start_download_intentservice"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开始intentservice下载"/>

写一个MyIntentService.java类,继承于IntentService,要在AndroidManifest.xml中注册

<service android:name=".MyIntentService"></service>
public class MyIntentService extends IntentService{    private int count;    /**     * Creates an IntentService.  Invoked by your subclass's constructor.     *     * @param name Used to name the worker thread, important only for debugging.     */    public MyIntentService(String name) {        super(name);    }    public MyIntentService() {        this("");    }    @Override   protected void onHandleIntent(Intent intent) {        Log.d("IntetnService","运行到了OnCreate");        while(count<100){            if (count>100){                count=0;            }            count++;            Intent intent1=new Intent();            intent1.setAction(MainActivity.DOWN_LOAD_ACTION);            intent1.putExtra("count",count);            sendBroadcast(intent1);            try {                Thread.sleep(200);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        try {            Thread.sleep(300);        } catch (InterruptedException e) {            e.printStackTrace();        }        Log.d("IntetnService","运行到了onStartCommand");    }}

在MainActivity.java中添加点击事件

public class MainActivity extends Activity {    private Button btn_start_service;    private Button btn_stop_service;    private Button btn_start_download;    private Button btn_intentservice;    private ProgressBar progressBar;    private MyDownLoadService mDownLoadService;    public static final String DOWN_LOAD_ACTION="com.service.text";    private AlarmManager mAlarmManager;    private BroadcastReceiverActivity mBroadcast;    private android.content.ContentResolver resolver;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btn_start_service= (Button) findViewById(R.id.start_service);        btn_start_service.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                startService(intent);            }        });        btn_stop_service= (Button) findViewById(R.id.stop_service);        btn_stop_service.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                stopService(intent);            }        });        mDownLoadService=new MyDownLoadService();        IntentFilter filter=new IntentFilter();        filter.addAction(DOWN_LOAD_ACTION);        registerReceiver(mDownLoadService,filter);        progressBar= (ProgressBar) findViewById(R.id.progressBar);        btn_start_download= (Button) findViewById(R.id.start_download);        btn_start_download.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyService.class);                startService(intent);            }        });        btn_intentservice= (Button) findViewById(R.id.start_download_intentservice);        btn_intentservice.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent=new Intent(getApplicationContext(),MyIntentService.class);                startService(intent);            }        });    }    class MyDownLoadService extends BroadcastReceiver{        @Override        public void onReceive(Context context, Intent intent) {            int count=intent.getIntExtra("count", 0);            progressBar.setProgress(count);        }    }    //解绑    @Override    protected void onDestroy() {        super.onDestroy();        unregisterReceiver(mDownLoadService);    }}

这里写图片描述

Android线程

这里写图片描述
这里写图片描述
这里写图片描述

利用线程更新UI界面,Hanler()

UI界面只允许主线程来更改UI界面绘制,不允许其他线程来更改界面的绘制,给否则会报错抛出异常。因此就需要想要更改UI界面的线程将要更改界面的消息通过Message传递给主线程,由主线程来完成界面的绘制,当有多条消息时,主线程会将这些消息放在一个消息队列中,等待主线程的处理,通过Handler将消息转递给主线程,然后通过Handler的handleMessage() 方法来对消息进行处理。

Message msg=new Message();msg.obj=count+"秒";msg.what=TIME_DESC;mhandler.sendMessage(msg);

Handler

 private Handler mhandler=new Handler(){        public void handleMessage(Message msg){            Log.d("秒数",""+count+msg);            switch(msg.what){                case TIME_DESC:                    String time= (String) msg.obj;                    btn_handler.setText(time);                    break;            }        }    };

这里就以倒计时定时器为例,界面activity_main.xml

 <TextView            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="倒计时"/>        <Button            android:id="@+id/btn_handler"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="60秒"/>

MainActivity.java

public class MainActivity extends Activity {    private int count=60;    private static  final  int TIME_DESC=0x23;    private Button btn_handler;    private Handler mhandler=new Handler(){        public void handleMessage(Message msg){            Log.d("秒数",""+count+msg);            switch(msg.what){                case TIME_DESC:                    String time= (String) msg.obj;                    btn_handler.setText(time);                    break;            }        }    };   @Override    protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         btn_handler= (Button) findViewById(R.id.btn_handler);         btn_handler.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                count=60;                Toast.makeText(getApplication(),"开始倒计时",Toast.LENGTH_SHORT).show();                new Thread(new Runnable() {                    @Override                    public void run() {                        while (count>0){                            count--;                            try {                                Thread.sleep(1000);                            } catch (InterruptedException e) {                                e.printStackTrace();                            }                            Message msg=new Message();                            msg.obj=count+"秒";                            msg.what=TIME_DESC;                            mhandler.sendMessage(msg);                            Log.d("秒数",""+count+msg);                        }                    }                }).start();            }        }); }

这里写图片描述

但这样写代码会有写繁琐,为了简洁,采用另外一种方法可以达到同样效果,前者使通过主线程里的封装好的Looper()方法来管理消息队列,这里我们可以通过一个自定义的Thread类来对消息进行管理,从而简洁了监听事件里的代码。

MainActivity.java中的按钮事件监听事件

public class MainActivity extends Activity {    private int count=60;    private static  final  int TIME_DESC=0x23;    private Button btnhandler;    private Handler handler=new Handler(){        public void handleMessage(Message msg){            Log.d("秒数",""+count+msg);           switch(msg.what){               case TIME_DESC:                  count--;                   btnhandler.setText(count+"秒");                   if (count>0){                       try {                           Thread.sleep(1000);                       } catch (InterruptedException e) {                           e.printStackTrace();                       }                       handler.sendEmptyMessage(TIME_DESC);                   }                   break;           }        }    };     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btnhandler= (Button) findViewById(R.id.btnhandler);        btnhandler.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                count=60;                handler.sendEmptyMessage(TIME_DESC);                       }        });     }}

这里写图片描述

子线程更新UI界面使通过子线程给主线程传递消息来更改UI界面,还可以互换一下,子线程可以接收来自主线程的消息。通过调用自定义的线程里的来让主线程发送消息,因此需要先调用启动线程的方法来启动线程里的Handler()来发送消息。

自定义的Thrad,MyThread .java写成内部类

class MyThread extends Thread{    @Override    public void run() {        Looper.prepare();        mHandler=new Handler(){            @Override            public void handleMessage(Message msg) {                Log.d("handler","接收到了主线程的消息");            }        };        Looper.loop();    }}

MainActivity.java

public class MainActivity extends Activity {    private Button btnhandler;    private int count=60;    private static  final  int TIME_DESC=0x23;    private Handler handler=new Handler(){        public void handleMessage(Message msg){            Log.d("秒数",""+count+msg);           switch(msg.what){               case TIME_DESC:                  count--;                   btnhandler.setText(count+"秒");                   if (count>0){                       try {                           Thread.sleep(1000);                       } catch (InterruptedException e) {                           e.printStackTrace();                       }                       handler.sendEmptyMessage(TIME_DESC);                   }                   break;           }        }    };    private Button btnHandler;    private Handler mHandler;    class MyThread extends Thread{    @Override    public void run() {        Looper.prepare();        mHandler=new Handler(){            @Override            public void handleMessage(Message msg) {                Log.d("handler","接收到了主线程的消息");            }        };        Looper.loop();    }} @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        btnHandler= (Button) findViewById(R.id.btnHandler);        btnHandler.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {               mHandler.sendEmptyMessage(0);            }        });        btnhandler= (Button) findViewById(R.id.btnhandler);        btnhandler.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                count=60;                handler.sendEmptyMessage(TIME_DESC);                MyThread thread=new MyThread();                thread.start();            }        });    }}

AsyncTask

这里写图片描述

为了子线程更好地对UI进行操作,Android还提提供了Handler之外一种工具AsyncTast。AsyncTast制定了三个参数,Params在执行AsyncTast时传入,可用于后台中进行的任务,Progress后台执行任务时,需要在界面上显示当前的进度,则使用这里的泛型作为进度单位,Result当任务执行完成后,需要对结果进行返回。

AsyncTask的泛型类型

  这三个类型被用于一个异步任务,如下:

  1. Params,启动任务执行的输入参数

  2. Progress,后台任务执行的百分比

  3. Result,后台计算的结果类型

4个步骤

    当一个异步任务被执行,任务经过四各步骤:

    1.onPreExecute(),在UI线程上调用任务后立即执行。这步通常被用于设置任务,例如在用户界面显示一个进度条。

    2.doInBackground(Params…),后台线程执行onPreExecute()完后立即调用,这步被用于执行较长时间的后台计算。异步任务的参数也被传到这步。计算的结果必须在这步返回,将传回到上一步。在执行过程中可以调用publishProgress(Progress…)来更新任务的进度。

    3.onProgressUpdate(Progress…),一次呼叫 publishProgress(Progress…)后调用 UI线程。执行时间是不确定的。这个方法用于当后台计算还在进行时在用户界面显示进度。例如:这个方法可以被用于一个进度条动画或在文本域显示记录。

    4.onPostExecute(Result), 当后台计算结束时,调用 UI线程。后台计算结果作为一个参数传递到这步。

任务实例必须创建在 UI线程

线程规则

  有一些线程规则必须去遵守,这个类才会正确的工作:任务实例必须创建在 UI线程

execute(Params…)必须在UI线程上调用

不要手动调用onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…)

    这个任务只执行一次(如果执行第二次将会抛出异常)

一个简单的自定义的AsyncTast,MyDownLoadService.java

class MyTask extends AsyncTask<String,String ,String>{    @Override    protected void onPostExecute(String s) {        super.onPostExecute(s);        btn_progressBar.setText(s);    }    @Override    protected void onProgressUpdate(String... values) {        super.onProgressUpdate(values);        int count1=Integer.parseInt(values[0]);        mprogressBar.setProgress(count1);    }    @Override    protected String doInBackground(String... params) {        while(count1<101){            count1++;            publishProgress(""+count1);            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return "下载已完成";    }}

依旧以下载进度条为例。MainActivity.java

public class MainActivity extends Activity {    private Button btn_progressBar;    private ProgressBar mprogressBar;    private int count1=0;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        mprogressBar= (ProgressBar) findViewById(R.id.progressBar2);        btn_progressBar= (Button) findViewById(R.id.btn_progressBar);        btn_progressBar.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                MyTask task=new MyTask();                task.execute("去执行吧");            }        });        class MyTask extends AsyncTask<String,String ,String>{    @Override    protected void onPostExecute(String s) {        super.onPostExecute(s);        btn_progressBar.setText(s);    }    @Override    protected void onProgressUpdate(String... values) {        super.onProgressUpdate(values);        int count1=Integer.parseInt(values[0]);        mprogressBar.setProgress(count1);    }    @Override    protected String doInBackground(String... params) {        while(count1<101){            count1++;            publishProgress(""+count1);            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        return "下载已完成";    }}}

activity_main.xml

<ProgressBar        style="?android:attr/progressBarStyleHorizontal"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:id="@+id/progressBar2" />    <Button        android:id="@+id/btn_progressBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="开始"/>

这里写图片描述

0 0
原创粉丝点击