您的位置:首页 > 移动开发 > Android开发

Android 多线程 和异步的实践:跳转,同步显示时间,倒计时的实现,知识点

2015-10-17 10:37 941 查看
Android 多线程 和异步的实践

模拟引导页,数秒后转向新的页面

从主mainactiyity 到newpager 写了两种启动模式

先写 布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="3S后跳转" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/aa"/>

</LinearLayout>


实现代码
package com.example.theadtest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends Activity {

private Handler mHandler;

Intent intent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// mHandler.postDelayed(new mythread(), 3000);//引导画面停留 6-8S

new Thread(new mythread()).start();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

class mythread implements Runnable {

@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
intent = new Intent(getApplicationContext(),
NewPagerActivity.class);
startActivity(intent);//启动方法 不属于UI
}
}
class MyThd extends Thread{

@Override
public void run() {
super.run();
long stime=System.currentTimeMillis();
//此处是逻辑计算加载资源时间 是否6S

long etime=System.currentTimeMillis();
long runtime=etime-stime;
try {
if (6000>runtime) {

Thread.sleep(6000-runtime);//一般定义为常量
}
else Thread.sleep(runtime);//一般定义为常量
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}


在新的页面
有一个倒计时 ,有一个同步显示的时间,还有一个计算距离某天还有多久

同样写了两个线程启动的方法 实现runable接口和 继承Thread 重写run的区别

启动 new继承类的start()方法  重建接口实现Runable的启动方式newthread (有一个runable参数的构造方法任务new Thread(new 自定义实现的的runnable).start();

区别:1.第一种是继承的关系单继承,第二种是实现接口的关系可以多个2.任务写死在线程,不能复用,但是实现接口的可以复用,多个线程共用一个任务,用runnable

在非UI 线程中不可以操作UI

为什么要使用多线程?

响应时间5s  弹出对话框 ANR错误  application Not responsibding

原因:1.主线程5秒内没有响应输入事件2. BroadcastReceiver没有在10秒内完成返回。

根本原因主线程被阻塞,解决办法:将耗时操作放在异步的子线程中处理。

如 1.数据库的大数据量操作2.大文件的I/O操作

1.      网络操作。4复杂运算

子线程和主线程的通信发送Message是处理数据数据是绑定在message

  通过Handler (处理机的意思)类作为通道负责发送和接收  在不同的线程间进行通信

Handler 的一个方法 obtainMessage();唯一性

可传递类型: arg1 .arg2 整形一般用来传递 简单的熟知数据

What 整形

Obj 对象数据 主要的数据绑定方式

Handler 发送 sendMessage()  接收handleMessage()

步骤

1.      构建一个Handler

2.      在需要通信的时候创建Message

3.      通过Handler 发送Message

4.      通过Handler 接收Message

Private Handler handle=new Handler ();

在线程中通讯处创建Message msg=new Message() {

加花括号就是重写其中的方法

写在主线程中 可以接受消息后 处理UI 需要重写private Handler
handler=new
Handler()
    {
        @Override
        public
void
handleMessage(Messagemsg) {
           
    }

};

Asytask 异步任务 泛型参数内部方法 启动

比handler 更轻量级使用简单的 异步处理

参数可以是Java 任意类数据类型如果不需要参数 可以传入void

Params 启动任务执行的输入参数,比如http 请求的URL

Progress 后台任务的百分比 用于线程执行的UI 交互

Result 后台执行的最终返回结果

内部方法

OnPreExecute() 当前任务执行之前 调用此方法

doInBackground(Params) 后台执行 比较耗时的操作放在此处

onProgressUpdate(Progress) 显示进度

onPostExecute(Result) 任务执行完 调用的方法 任务执行的结果作为参数

 

接程序代码
新的页面 布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<TextView
android:id="@+id/text_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/hello_world" />
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击开始倒计时"
/>
<TextView
android:gravity="center_horizontal"
android:id="@+id/text_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="当前时间" />
<TextView
android:id="@+id/tag_time"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="距离还有" />
<TextView
android:gravity="center_horizontal"
android:id="@+id/dao_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:text="倒计时" />

</LinearLayout>


java代码
package com.example.theadtest;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import android.R.integer;
import android.app.Activity;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.
4000
Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class NewPagerActivity extends Activity {
private TextView text_display, tag_time, text_time, dao_time;
private Button btn;
private Handler handler;
private static boolean state = false;
private static final String TIME_STRING = "2015-10-31-23-59-59";//把目标截止时间定义为常量,方便修改

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_new_pager);
text_time = (TextView) findViewById(R.id.text_time);
text_display = (TextView) findViewById(R.id.text_display);
dao_time = (TextView) findViewById(R.id.dao_time);
tag_time = (TextView) findViewById(R.id.tag_time);
btn = (Button) findViewById(R.id.btn);
tag_time.setText("距离" + TIME_STRING);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case 0:
String stime = msg.obj.toString();
text_time.setText(stime);
break;
case 1:
String s1 = msg.obj.toString();
if (Integer.parseInt(s1) <= 10) {
text_display.setTextColor(Color.CYAN);
text_display.setText(s1);
if (Integer.parseInt(s1) == 0) {
text_display.setText("Duang!!!!");

}
} else
text_display.setText(s1);
break;
default:
break;
}
}
};
btn.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
new Mytime().start();
new Thread(new MyClick()).start();
// 开启异步任务
MyTask task = new MyTask();
task.execute();
}
});
}

class MyTask extends AsyncTask<Integer, Integer, Boolean> {

// 参数,对象类型1,启动的初始化数据 2,异步任务进度交互的数据 3,运行结果
/**
* @Override 即将启动的时候触发 一般用于准备工作
*/
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
dao_time.setText("-----开始!");// 纯属测试用的无意义
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.e("", "------------onPreExecute");
}

/**
* @Override
* 在异步任务运行个过程中 与UI交互的方法
*/
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
int timespan = values[0] / 1000;
long day = timespan / 86400;
long hour = timespan / 3600 - day * 24;
long min = timespan / 60 - hour * 60 - day * 24 * 60;
long sec = timespan % 60;
String txtString = "还有" + day + "天" + hour + "小时" + min + "分" + sec
+ "秒";
dao_time.setText(txtString);
}

/**
* @Override
* 惟一一个非UI线程运行的方法 主要处理异步任务
*/
protected Boolean doInBackground(Integer... params) {
int timespan = 0;
// 自定义时间格式
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
// 根据定义state状态判定activity是否被销毁,否则可能,返回了,这个异步任务还在执行。
while (true && !state) {
try {
Thread.sleep(1000);
long endDate = s.parse(TIME_STRING).getTime();
long nowDate = System.currentTimeMillis();
timespan = (int) (endDate - nowDate);
if (timespan <= 0) {
return true;
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(timespan);
}
return true;
}
/**
* @Override 异步任务运行完毕后触发
*/
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
Log.e("", "------------onPostExecute");

if (result = true) {
dao_time.setText("活动倒计时结束");
Log.e("", "------------结束");
}
super.onPostExecute(result);
}
}

// Thread 使用 继承
class Mytime extends Thread {
public void run() {
while (true && !state) {

try {
Message msg = Message.obtain();
String s = new SimpleDateFormat("yyyy年-MM月-dd日-HH时-mm分-ss秒")
.format(System.currentTimeMillis());
msg.obj = "当前时间" + s;
msg.what = 0;
handler.sendMessage(msg);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
}

// 实现接口
class MyClick implements Runnable {

public void run() {
try {
for (int i = 10; i >= 0; i--) {
Message msg = Message.obtain();
msg.obj = i;
msg.what = 1;
handler.sendMessage(msg);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

/**
* @Override
* activity销毁,改变state 异步里的doInBackground方法终止 返回true
*/
protected void onDestroy() {
// TODO Auto-generated method stub
state = true;
Log.e("", "------------onDestroy");
super.onDestroy();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.new_pager, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}


截图如下,显示最后相加少了一秒,应该是,当前正在进行的那一秒!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  倒计时 异步 多线程