哈?现在android版块都没认真对待学习的人了?

解决方案 »

  1.   

    我觉得从代码上来看是看handler的构造函数,handler会对自己的mLooper进行初始化,
    如果是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()来判断是否是主线程……没试过,等下写个例子自己剩下
      

  2.   

    刚才写了个例子,验证了一下这个问题 。
    1.handler实例化时如果用的主线程的looper 那通过handler的对像,发过去的消息是在主线程处理的。
    如果handler实例化时如果用的子线程的looper那么通过handler的对像发送消息,是在子线程中处理。
    2.要想获取handler 实例运行的线程则用:handler.getLooper().getThread().getName()来获取
      

  3.   

     安卓下建立socket就崩溃,分到子线程仍然不行,求助啊。
    原代码如下,如果我不用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();
                }
            }
    }
    }
      

  4.   

    1、
    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
      

  5.   

    1、
    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的程序放在里面,但是如果按键监听存在的话就不行的。。不知道啥原因
      

  6.   

    我自己试的时候把那些给UI赋值的都注释掉了。就留下一个NEW SOCKET(“ip”,PORT),不用按键监听的时候可以建立连接,但是用按键就显示不能再主线程里网络操作了,但是我已经是在new thread里运行了呀,实在想不明白呢
      

  7.   

    答案已经很接近了,可以看下looper的源码,它是怎么获取到messagequen的
      

  8.   

    你想表达的是这个意思,我回答的可能与你问的不是一个问题 
    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();
                }
            }
        }
      

  9.   


    又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!
      

  10.   


    又看了一遍这个问题 ,其实问题是有问题 的,send,或post过去的不一定是主线程,也可能是子线程,因为当构建handler时在子线程中,那POST或send过去一定是在子线程 中的,这个写例子已验证!其实就是看你的looper是在哪里实例化的,一个looper有一个MessageQueue,你的handler如果在子线程中实例化了,是否实例化looper,如果实例化就发送到子线程了,否则activity初始化的时候会初始化主线程的looper
      

  11.   

    版主的帖子以及各位回复让我获益良多,我没有看过android源码,但使用起来都是以直觉来使用,平时都是handler声明的同时实例化的,其所有是主线程就是主线程,是子线程就归子线程,比较直观,倒也没有出什么问题,现在发现还有这些道道。
      

  12.   

    handler很常用的东东,在子线程中发送消息通知主线程更新UI等只能在主线程做的操作。