展会信息港展会大全

Android两activity返回事件中返回数据 刷新界面 多线程和双缓冲
来源:互联网   发布日期:2016-01-14 10:21:34   浏览:2220次  

导读:1 引用函数 setResult和 onActivityResult处理机制 实现原理,在第二个Activity的返回事件中返回数据,第一个Activity中重构onActivityResult方法,在重构该方法的事件中,感觉返回的数据,做出不同的处理。 ...

1 引用函数 setResult和 onActivityResult处理机制

实现原理,在第二个Activity的返回事件中返回数据,第一个Activity中重构onActivityResult方法,在重构该方法的事件中,感觉返回的数据,做出不同的处理。以达到自动更新第一个Activity的效应。详细情况参考如下的介绍。当前两个 activity,MainAcivity和SecondActivity;

A MainAcivity的重要代码:

public void onClick(View v) {

Intent intent = new Intent();

intent.setClass(MainActivity.this, SecondActivity.class);

Bundle bundle = new Bundle();

Log.v("android.abc", "!!!!!"+MainActivity.this.toString());

bundle.putString("uid", MainActivity.this.toString());

intent.putExtras(bundle);

startActivityForResult(intent,GET_CODE);

}

B.SecondActivity中,在OnClickListener中

findViewById(R.id.button).setOnClickListener(new View.OnClickListener()

{

@Override

public void onClick(View v)

{

setResult(RESULT_OK,(new Intent()).setAction(uid));

finish();

}

});

B.在MainActivity中,重写onActivityResult方法;

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data)

{

if(requestCode == GET_CODE)

{

if(resultCode == RESULT_CANCELED)

{

text2.setText("点击了返回");

}

else

{

if (data != null)

{

text2.setText("得到第二个activity返回的结果:\n"+data.getAction());

}

}

}

}

其中static final private int GET_CODE = 0;是我自定义的常量,用来区分当前返回的是哪个activity的结果;下面是类SecondActivity的代码:

public class SecondActivity extends Activity{

String uid;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.second);

Bundle bundle = this.getIntent().getExtras();

if (bundle != null)

{

uid = bundle.getString("uid");

}

findViewById(R.id.button).setOnClickListener(

new View.OnClickListener()

{

@Override

public void onClick(View v)

setResult(RESULT_OK,(new Intent()).setAction(uid));

finish();

}

});

}

}

//

public void startActivityForResult (Intent intent, int requestCode)

启动一个Activity且传递一个requestCode值,在本Activity推出时,在启动的Activity的 onActivityResult()的方法中将会被调用到这个

传递的这个requestCode值。忽略这个requestCode值,实际上startActivityForResult跟 startActivity(Intent)没有什么差别

注意,该方法只适用那些需要有一个返回值的Intent。在其他协议(如ACTION_MAIN或ACTION_VIEW),你可能不会得到当你期望的结果。举个例子

,如果 你启动的activity 采用了singleTask模式,它将不会运行在你的任务,因此你将收到一个取消的结果。作为一种特殊的情况下,在初始化

activity的onCreate(BundlesavedInstanceState)/onResume() of your activity期间,如果你调用参数requestCode > = 0的

startActivityForResult(),那么在窗口中将不会显示返回来的结果,这是为了在连接到另一个activity时避免闪烁

protected void onActivityResult (int requestCode, int resultCode, Intent data)

Called when an activity you launched exits, giving you the requestCode you started it with, the resultCode

it returned, and any additional data from it. The resultCode will be RESULT_CANCELED if the activity explicitly returned

that, didn't return any result, or crashed during its operation.

You will receive this call immediately before onResume() when your activity is re-starting.

Parameters

requestCodeThe integer request code originally supplied to startActivityForResult(), allowing you to identify who this

result came from.

resultCodeThe integer result code returned by the child activity through its setResult().

dataAn Intent, which can return result data to the caller (various data can be attached to Intent "extras").

//

2 引用函数 onResume处理机制

在每一个可能在改变语言区域的Activity 之前显示出来的Activity中,重载onResume()并加入如下代码:

oldLocale = mLocale;

Locale locale = getLocaleFormPreference(this);

if(oldLocale!=null && !oldLocale.equals(locale)) {

Bundle bundle = new Bundle();

activity.onSaveInstanceState(bundle);

Intent intent = new Intent(this, this.getClass());

intent.putExtra("InstanceState", bundle);

intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);

startActivity(intent);

finish();

}

并在onCreate(Bundle savedInstanceState)最后加入和动态更新时完全相同的代码。mLocale 实际上是在onCreate(Bundle savedInstanceState)中,指定的Locale 时(也就是上一节最初时那段代码)记住的。而如果,你的Activity启动需要要一些原有Intent 的数据,别忘了自行导入

3 利用Handler刷新界面

Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。实例化一个Handler对象,并重写handleMessage方法调用 invalidate()实现界面刷新;而在线程中通过sendMessage发送界面更新消息。

// 在onCreate()中开启线程

new Thread(new GameThread()).start();、

// 实例化一个handler

Handler myHandler= new Handler()

{

//接收到消息后处理

public void handleMessage(Message msg)

{

switch (msg.what)

{

case Activity01.REFRESH:

mGameView.invalidate();//刷新界面

break;

}

super.handleMessage(msg);

}

};

class GameThread implements Runnable

{

public void run()

{

while (!Thread.currentThread().isInterrupted())

{

Message message = new Message();

message.what = Activity01.REFRESH;

//发送消息

Activity01.this.myHandler.sendMessage(message);

try

{

Thread.sleep(100);

}

catch (InterruptedException e)

{

Thread.currentThread().interrupt();

}

}

}

}

4使用postInvalidate()刷新界面

使用postInvalidate则比较简单,不需要handler,直接在线程中调用postInvalidate即可。

class GameThread implements Runnable

{

public void run()

{

while (!Thread.currentThread().isInterrupted())

{

try

{

Thread.sleep(100);

}

catch (InterruptedException e)

{

Thread.currentThread().interrupt();

}

//使用postInvalidate可以直接在线程中更新界面

mGameView.postInvalidate();

}

}

}

5 多线程和双缓冲

A.不使用多线程和双缓冲

这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate() 方法即可。系统会自动调用 View的onDraw()方法。

B.使用多线程和不使用双缓冲

这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.

这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的 Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法)。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。

Java代码

new Thread(new Runnable() {

@Override

public void run() {

while(true){

try {

.timeViewHandler.sendMessage(Message.obtain(timeViewHandler, MSG_UPDATE));

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

Java代码

public class TimeViewHandler extends Handler {

private TextView timeView;

public TextView getTimeView() {

return timeView;

}

public void setTimeView(TextView timeView) {

this.timeView = timeView;

}

public TimeViewHandler(TextView timeView) {

super();

this.timeView = timeView;

}

@Override

public void handleMessage(Message msg) {

switch (msg.what) {

case MSG_UPDATE:

timeView.setText(DateHelper.getNow("kk:mm:ss"));

timeView.invalidate();

break;

}

super.handleMessage(msg);

.}

}

C 使用多线程和双缓冲

Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现 SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要 android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用 unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。

Java代码

public class TouchDrawView extends SurfaceView implements SurfaceHolder.Callback{

private SurfaceHolder holder;

private TouchDrawListener listener;

public TouchDrawListener getListener() {

return listener;

}

public void setListener(TouchDrawListener listener) {

this.listener = listener;

}

public TouchDrawView(Context context) {

super(context);

holder = getHolder();

holder.addCallback(this);

listener = new TouchDrawListener(holder);

listener.setShape(TouchDrawListener.SHAPE_LINE);

listener.setShape_style(TouchDrawListener.SHAPE_STYLE_FILL);

this.setOnTouchListener(listener);//设置屏幕事件监听器

this.setLongClickable(true);//不设置将无法捕捉onFling()事件

setFocusable(true);//设置键盘焦点

.setFocusableInTouchMode(true);//设置触摸屏焦点

}

public TouchDrawView(Context context, AttributeSet as) {

this(context);

}

@Override

protected void onDraw(Canvas canvas) {

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

}

@Override

public void surfaceCreated(SurfaceHolder holder) {

//关键部分

Canvas canvas = holder.lockCanvas(null);//获取画布

canvas.drawColor(Color.WHITE);//白色背景

holder.unlockCanvasAndPost(canvas);//解锁画布,提交画好的图像

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

}

}

赞助本站

人工智能实验室
AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港