Android中Activity和Handler的运行机制

Listening_music 2011-10-28 09:38:39
刚学Android没多久哈,所以好多运行中的机制不是很清楚呢>_<
1、Android中如果创建了一个主Activity,也就是创建了一个主线程,那这个主线程有没有run方法?还有如果在Activity的onCreate方法中给button设置了监听,后面点击按钮出发Click事件,那个onCreate方法并没有再次执行,为什么还是能执行onCreate方法中的onClick方法呢?
2、还在就是如果我在主线程中创建一个Handler并且就是绑定到这个主线程的Looper上的(先不管这个有没有实际意义哈,我知道handler用在线程间消息传递才能看出他的强大哈~),具体情况请看一下下面的代码:
package com.test.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class ChildSet extends Activity {
/** Called when the activity is first created. */
private ProgressBar myProgressbar;
private Button myButton;
private OnClickListener listener;
private Runnable childThread;
private static final String TAG = "TAG";
Myhandler mainHandler, childHandler;
private int i = 0;

// private Thread t;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

myProgressbar = (ProgressBar) findViewById(R.id.progressbar_id);
myButton = (Button) findViewById(R.id.button_id);

Log.i(TAG, "Main Thread:" + Thread.currentThread().getName());
// HandlerThread handlerThread = new HandlerThread("child_ron_Thread");
// handlerThread.start();

mainHandler = new Myhandler(Looper.getMainLooper());
// childHandler = new Myhandler(handlerThread.getLooper());// $$$$$$$$$$$$$

myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (i == 0) {
myProgressbar.setVisibility(ProgressBar.VISIBLE);
mainHandler.post(childThread);
i = i + 1;
}
// myProgressbar.setProgress(80);//这个可以设置的哟~~~
Log.i(TAG, "Click..." + Thread.currentThread().getName());
}
});
childThread = new Runnable() {
int persent = 0;

@Override
public void run() {
// TODO Auto-generated method stub
persent += 5;
Message msg = Message.obtain();
msg.arg1 = persent;
Log.i(TAG, "Runnable Thread:"
+ Thread.currentThread().getName());

// mainHandler.sendMessage(msg);
mainHandler.sendMessage(msg);
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
};
}

// //////////////////////////onCreate////////////////////////////
class Myhandler extends Handler {
public Myhandler(Looper looper) {
super(looper);
}

public void handleMessage(Message msg) {
myProgressbar.setProgress(msg.arg1);
Log.i(TAG, "handleMessage Thread:"
+ Thread.currentThread().getName());
mainHandler.post(childThread);
// 在子线程中处理,主线程中对button的响应很快;如果这边改成主线程处理则对主线程按钮的响应就慢了
if (msg.arg1 >= 100) {
mainHandler.removeCallbacks(childThread);
}
}
}
}

以上代码运行的时候为什么一定是等run方法运行完了,再等handleMessage运行结束才会响应我的button点击事件,如果是抛出消息之后就handleMessage的话,那我在handleMessage里面也抛出线程了,为什么没有就再直接去执行那个线程的run方法,而是可以就去响应之前的button点击事件了呢?这个监听器到底是怎么运行的呢?
可能因为我懂的太少,然后又理解的太浅,所以问的问题可能比较那什么哈,希望大家帮忙解释一下啦~~~
...全文
1056 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Listening_music 2011-10-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fenger8293 的回复:]

1.设置onClickListener后就是给Button设置了一个监听接口。在Button类的onClick处理时会来回调你设置的接口函数。这也是android最常用的一个机制,在很多组件里都采用了这种回调的机制。
2.我不知道你和http://topic.csdn.net/u/20111027/23/ef6599ef-cba8-4726-bae5-e9fdd457c370.html
这个……
[/Quote]


先申明一下哈,我不是你说的那个同一个发帖人的人啦~
还有,你在那个帖子里说不需要我们主动去remove那个回调函数,那我最后点击BACK按键结束该进程的时候为什么那个handleMessage还是一直在执行呢?就算我在onDestroy函数里remove回调了,也结束了创建的子进程了也还是在一直抛消息和处理消息呀,这是为什么呢?
额……我的代码:
package com.test.handler;

import android.R.integer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class MultiThreadHandler extends Activity {
private ProgressBar myProgressBar;
private Button myButton;

HandlerThread barThread = new HandlerThread("ChildThread");
myHandler barHandler;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

myProgressBar = (ProgressBar) findViewById(R.id.progressbar_id);
myButton = (Button) findViewById(R.id.button_id);

// HandlerThread barThread = new HandlerThread("myThread");
barThread.start();
barHandler = new myHandler(barThread.getLooper());
// myHandler barHandler = new myHandler(barThread.getLooper());
myProgressBar.setProgress(10);
Log.i("TAG", "onCreate ---> " + Thread.currentThread().getName());

Message msg = barHandler.obtainMessage();
msg.arg1 = 0;
msg.sendToTarget();
myButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
myProgressBar.setProgress(70);
Log.i("TAG", "Click the Button...");
Message msg = barHandler.obtainMessage();
msg.arg1 = 80;
msg.sendToTarget();
barHandler.post(barThread);
// myProgressBar.setProgress(60);

}
});
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
barHandler.removeCallbacks(barThread);
barThread.stop();
}

class myHandler extends Handler {
public myHandler() {

}

public myHandler(Looper myLooper) {
super(myLooper);
}

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
int ms = msg.arg1;
Log.i("TAG", "handlerMessage ---> "
+ Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myProgressBar.setProgress(50);// //////////////////////////////////////
Log.i("TAG", "The message here is " + ms);
Message msg1 = barHandler.obtainMessage();
if (msg1.arg1 < 100) {
msg1.arg1 = msg1.arg1 + 10;
msg1.sendToTarget();
// barHandler.post(barThread);
}
}
}
}


这个我必须要把模拟器都关了才有用……
Listening_music 2011-10-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fenger8293 的回复:]

你的代码还是有多处的问题。
1.你的myHandler实例代码是在HandlerThread线程里执行的,对于非UI线程是不允许直接操作UI上的组件的。
2.barHandler.removeCallbacks(barThread); Handler去remove一个线程是错误的用法,虽然Thread因为实现了Runnable接口,所以在语法上不会存在错误。但这个方法的作用是取消原先设置的延……
[/Quote]
谢谢你了哈,我刚刚弄懂了,刚刚回帖上面的那个其实只要把那个自定义的线程类换成Runnable接口就可以了,因为post的是Runnable对象呢,然后那个什么时候用mainHandler,什么时候用childHandler就像上个回帖上面说的那样了。
真的真的谢谢你耐心的解释哟~
wyx100 2011-10-28
  • 打赏
  • 举报
回复
1.设置onClickListener后就是给Button设置了一个监听接口。在Button类的onClick处理时会来回调你设置的接口函数。这也是android最常用的一个机制,在很多组件里都采用了这种回调的机制。
2.我不知道你和http://topic.csdn.net/u/20111027/23/ef6599ef-cba8-4726-bae5-e9fdd457c370.html
fmworld 2011-10-28
  • 打赏
  • 举报
回复
楼上正解
手指风 2011-10-28
  • 打赏
  • 举报
回复
1.设置onClickListener后就是给Button设置了一个监听接口。在Button类的onClick处理时会来回调你设置的接口函数。这也是android最常用的一个机制,在很多组件里都采用了这种回调的机制。
2.我不知道你和http://topic.csdn.net/u/20111027/23/ef6599ef-cba8-4726-bae5-e9fdd457c370.html
这个帖子是不是同一个发帖人。我在后面回复的比较详细了。
凉凉二点凉 2011-10-28
  • 打赏
  • 举报
回复
你的mainThread是阻塞的,当然就会出现你说的那种情况


Looper.getMainLooper()

看到你写的没?其实达到你说的那种效果其实很简单,不要跟主线程绑定
用如下代码就行

HandlerThread hThread = new HandlerThread("test");
hThread.start();
mainHandler = new Myhandler(hThread.getLooper());
Listening_music 2011-10-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 fenger8293 的回复:]

你的代码还是有多处的问题。
1.你的myHandler实例代码是在HandlerThread线程里执行的,对于非UI线程是不允许直接操作UI上的组件的。
2.barHandler.removeCallbacks(barThread); Handler去remove一个线程是错误的用法,虽然Thread因为实现了Runnable接口,所以在语法上不会存在错误。但这个方法的作用是取消原先设置的延……
[/Quote]
真的非常非常感谢你的耐心呀~最后一个问题哈~~
就说网上说的最多的一个case吧:就是在主线程中更新进度条,在另起的一个线程中给主线程发送消息,并传值给主线程,然后在主线程中接收那个消息,并取得发送过来的值,用这个值去设置进度条的进度,并且再次让那个另起的线程运行run方法并再给主线程发送更新进度条的消息,最后在进度条满了的时候就结束消息发送。
你看我这样做还行?
package com.test.handler;

import com.test.handler.MultiThreadHandler.Myhandler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;

public class Final extends Activity {

private Button myButton;
private ProgressBar myProgressBar;
MyHandler mainHandler, childHandler;
MyHandlerThread myHandlerThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myButton = (Button) findViewById(R.id.button_id);
myProgressBar = (ProgressBar) findViewById(R.id.progressbar_id);

myHandlerThread = new MyHandlerThread("Children_Thread");
myHandlerThread.start();

mainHandler = new MyHandler(getMainLooper());
childHandler = new MyHandler(myHandlerThread.getLooper());

Log.i("TAG","Thread---" + Thread.currentThread().getName() + " onCreate");
myButton.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i("TAG","Thread---" + Thread.currentThread().getName() + " Click~~~~~~~~~~");
childHandler.post(myHandlerThread);//用子线程的Handler来post,依旧在子线程中运行run方法?????
}
});
}

class MyHandlerThread extends HandlerThread {

int i = 0;
public MyHandlerThread(String name) {
super(name);
// TODO Auto-generated constructor stub
}

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
i = i + 10;
if(i < 100) {
Log.i("TAG","Thread---" + Thread.currentThread().getName() + " i ---> " + i);
Message msg = mainHandler.obtainMessage();
msg.arg1 = i;
mainHandler.sendMessage(msg); //send到main线程的消息队列中,然后在main的handleMessage里用这个值设置进度条
}
if(i > 100) {
Log.i("TAG","Thread---" + Thread.currentThread().getName() + " removeCallbacks.......");
mainHandler.removeCallbacks(null);
}
}
}

class MyHandler extends Handler {

public MyHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
myProgressBar.setProgress(msg.arg1);
Log.i("TAG","Thread---" + Thread.currentThread().getName() + " The msg here ---> " + msg.arg1);
childHandler.post(myHandlerThread);
}
}
}

但是运行的时候我点击按钮就报错,提示不能在一个线程里创建多个Looper…………
但是按我的理解就是在点击按钮后用子线程的Handler去post,然后执行那个run方法,接着在run方法里用主线程的mainHandler去把消息发送到主线程,再在主线程中的handleMessage方法里设置进度条,并且再次用子线程的Handler去post,从而让子线程的run方法再次执行,我这样理解对么?
再麻烦你帮我解释一下上面的问题好不好?谢谢你喽O(∩_∩)O~
knxw0001 2011-10-28
  • 打赏
  • 举报
回复
要不要发这么多代码啊Aa
手指风 2011-10-28
  • 打赏
  • 举报
回复
回调函数是android的很常见的一种事件处理机制,是一种由系统来回调你指定的函数的做法。按钮的监听即是如此,你设置一个监听接口,该接口有个方法,你必须实现这个接口方法,然后指定按钮的Click监听为该接口对象。当该按钮被Click时候,系统收到Click事件后发现其设置了监听接口,于是来回调这个接口的onClick方法
手指风 2011-10-28
  • 打赏
  • 举报
回复
你的代码还是有多处的问题。
1.你的myHandler实例代码是在HandlerThread线程里执行的,对于非UI线程是不允许直接操作UI上的组件的。
2.barHandler.removeCallbacks(barThread); Handler去remove一个线程是错误的用法,虽然Thread因为实现了Runnable接口,所以在语法上不会存在错误。但这个方法的作用是取消原先设置的延时回调。
3.对post和sendToTarget不理解,乱用。barHandler.post(barThread)这句没有任何意义。因为Handler的post方法作用在于执行一个runnable,你传的是一个线程(HandlerThread也是从Thread继承下来),你没有继承HandlerThread并重写run(runnable接口的接口方法),默认它是一个空方法。sendToTarget会给对应的handler添加一个消息,而你在这个消息处理里又调用一次sendToTarget,从而造成子线程死循环。
4.HandlerThread没有在任何地方看到调用其quit或者是其Looper的quit方法来退出消息循环,加上上面第3点,你的消息循环会一直处理。需要注意,即时没有消息处理也必须调用其quit方法来结束消息循环。
Listening_music 2011-10-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 fenger8293 的回复:]

1.设置onClickListener后就是给Button设置了一个监听接口。在Button类的onClick处理时会来回调你设置的接口函数。这也是android最常用的一个机制,在很多组件里都采用了这种回调的机制。
2.我不知道你和http://topic.csdn.net/u/20111027/23/ef6599ef-cba8-4726-bae5-e9fdd457c370.html
这个……
[/Quote]
还有呀,你说的那个回调机制怎么理解呢?问题多了些,不要介意哈,谢谢帮忙喽~~

80,471

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧