哈?现在android版块都没认真对待学习的人了?
解决方案 »
- 求助!在Android平台下开发音乐播放器,怎样让系统自动扫描加载歌曲的时候扫描指定文件夹,还有下载歌曲的时候怎样下载到指定文件夹?
- android 4.0.3 HDMI输出分辨率问题
- android 卸载和装载内存卡 代码
- ubuntu中 android源代码的使用求教
- android怎么才能获得联通/移动的手机号
- android中数据库操作时报错
- 请各位帮忙解释几个方法?
- 初级菜鸟-ArrayAdapter构造函数第二个参数具体指什么
- android view移动与显示的问题 各位大神 在线等 挺急的
- 请问各位大神这个问题怎么解决
- 安卓手机管理所有接入无线热点的设备
- ListView 点击一个按钮后,出现滑动
如果是public Handler(Callback callback, boolean async)这类构造函数(包括public Handler(boolean async),public Handler(Callback callback),public Handler())
则是mLooper = Looper.myLooper();mLooper 是当前线程looper……否则就是public Handler(Looper looper, Callback callback, boolean async)这样带looper的构造函数handler有getLooper方法,就是返回mLooper
貌似可以试着用mLooper == Looper.getMainLooper()来判断是否是主线程……没试过,等下写个例子自己剩下
1.handler实例化时如果用的主线程的looper 那通过handler的对像,发过去的消息是在主线程处理的。
如果handler实例化时如果用的子线程的looper那么通过handler的对像发送消息,是在子线程中处理。
2.要想获取handler 实例运行的线程则用:handler.getLooper().getThread().getName()来获取
原代码如下,如果我不用BUTTON去触发的话是可以建立SOCKET的,但是用上BUTTON,把建立SOCKET的方法放到子线程中,仍然exception会显示不能再主线程中使用网络操作,真心求解为什么,看了2天了,刚学JAVA,不太理解。
public class MainActivity extends ActionBarActivity {
private EditText editText;
private Button button;
private TextView MTextview;
Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.editText1);
button = (Button)findViewById(R.id.button1);
final RunnableThread runnable = new RunnableThread();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(runnable);
}
});}
public class RunnableThread implements Runnable
{
public void run() {
Socket socket = null;
String message = editText.getText().toString()+ "\r\n" ;
try { //创建客户端socket,注意:不能用localhost或127.0.0.1,Android模拟器把自己作为localhost
socket = new Socket("172.16.5.30",8000); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter
(socket.getOutputStream())),true);
//发送数据
out.println(message); //接收数据
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String msg = in.readLine();
if (null != msg){
editText.setText(msg);
System.out.println(msg);
}
else{
editText.setText("data error");
}
out.close();
in.close();
} catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally{
try {
if (null != socket){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Handler handler=new Handler();
这个handler是创建在主线程里的,原因我在4楼说了,它的looper是当前线程的looper,也就是主线程了post的话,就是把runable加入主线程的消息队列,自然会报错最简单的处理方式:你new一个Thread,在start就可以了。或者自己获取一个线程的looper,再重新构造handler
2、if (null != msg){
editText.setText(msg);//不要在线程里面更新UI,例如这句为editText赋值
System.out.println(msg);
}
else{
editText.setText("data error");//不要在线程里面更新UI,例如这句为editText赋值
}可以改为发消息到主线程的handler更新view
Handler handler=new Handler();
这个handler是创建在主线程里的,原因我在4楼说了,它的looper是当前线程的looper,也就是主线程了post的话,就是把runable加入主线程的消息队列,自然会报错最简单的处理方式:你new一个Thread,在start就可以了。或者自己获取一个线程的looper,再重新构造handler
2、if (null != msg){
editText.setText(msg);//不要在线程里面更新UI,例如这句为editText赋值
System.out.println(msg);
}
else{
editText.setText("data error");//不要在线程里面更新UI,例如这句为editText赋值
}可以改为发消息到主线程的handler更新view
我也尝试过直接new Thread(){
}.start();我把那段建立socket的程序放在里面,但是如果按键监听存在的话就不行的。。不知道啥原因
looper的源码中写的很明白,在创建looper 对像时,在他的构造函数中初始化了一个接收处理message的队列,在启动looper的loop()方法中,一直不停的循环读取message 队列中的消息,然后回调给handler
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf("Looper", "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycle();
}
}
}
又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!
又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!其实就是看你的looper是在哪里实例化的,一个looper有一个MessageQueue,你的handler如果在子线程中实例化了,是否实例化looper,如果实例化就发送到子线程了,否则activity初始化的时候会初始化主线程的looper