安卓,主线程和子线程间传递消息,出错·,求大家帮我看看

我的代码如下:

activitymain.xml:

xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="vertical">

android:id="@+id/t1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击这里进行消息传递"/>

android:id="@+id/t2"
android:layout_width="192dp"
android:layout_height="49dp" />

MainActivity.java

package com.example.test3;

import android.os.Bundle;
import android.widget.TextView;
import android.app.Activity;
import android.view.Menu;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.Button;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {
Button but=null;
TextView textview=null;
Handler handler1,handler2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
but=(Button)super.findViewById(R.id.t1);
textview=(TextView)super.findViewById(R.id.t2);
Print p=new Print();
p.start();

    handler1=new Handler()
    {
        public void HandleMessage(Message msg)
        {
            if(msg.what==101)
                MainActivity.this.textview.setText(msg.getData().getString("toMain").toString());
        }
    };
    but.setOnClickListener(new OnClickListenerimpl());

}


@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 Print extends Thread
{
    public void run()
    {
        final Message msgReply=handler1.obtainMessage();
        Looper.prepare();
        handler2=new Handler(){

        public void handleMessage(Message msg)
        {
             if(msg.what==100)
             System.out.println("接收到了来自主线程的消息");

             msgReply.what=101;
             Bundle bundle=new Bundle();
             bundle.putString("toMain", "返回的消息");
             msgReply.setData(bundle);
             handler1.sendMessage(msgReply);
        }

        };

        Looper.loop();
    }
}

class OnClickListenerimpl implements OnClickListener
{
    public void onClick(View v)
    {
        if(MainActivity.this.handler2 != null)
        {Message msg=handler2.obtainMessage();
        msg.what=100;
        handler2.sendMessage(msg);
        }
    }
}

}

然后,如下是logcat:
图片说明

运行程序后,当按下一次按钮后,logcat里只会出现”接收到了来自主线程的消息“,如图中的第一行。但是等待一段时间该程序仍不会显示”返回的消息“,然后再按下一次按钮,一下子logcat就会弹出图中除第一行外的提示信息(图中最高两行是”接收到了来自主线程的消息“,第一个是第一次按按钮弹出的,第二个及以下的是第二次按下按钮弹出的”)。同时程序会强制退出,并提示“抱歉,已强行关闭”。

希望大家能帮我看看是怎么回事?

6个回答

试着把final Message msgReply放到handler2的handleMessage里,每次收到主线程消息之后再获得一个Message对象用来回复,而不是在run里定义一个然后一直用

zlp1992
zlp1992 回复freedom_wings: 我按照你写的能主线程能接收到子线程的消息啊,UI的textView的文本会改变,多次点击也没问题,代码见下面
4 年多之前 回复
freedom_wings
freedom_wings 按照你这样改了之后,程序就不会强退,但是每按一次按钮,后台都会输出“接收到了来自主线程的消息”,但是之后就没了,就是说子线程传递不了消息到主线程。当然原来也应该有这个问题,请问这里该如何解决?
4 年多之前 回复
 handler1=new Handler()
    {
        public void HandleMessage(Message msg)
        {
            if(msg.what==101)
                MainActivity.this.textview.setText(msg.getData().getString("toMain").toString());
        }
    };

        handler2=new Handler(){

        public void handleMessage(Message msg)
        {
             if(msg.what==100)
             System.out.println("接收到了来自主线程的消息");

             msgReply.what=101;
             Bundle bundle=new Bundle();
             bundle.putString("toMain", "返回的消息");
             msgReply.setData(bundle);
             handler1.sendMessage(msgReply);
        }

        };

        @Override
protected void onCreate(Bundle savedInstanceState) {
            //............省略
}

把创建的代码放在外面试试。

freedom_wings
freedom_wings 你这样不是就都在主线程里面了吗?
4 年多之前 回复
    handler1 = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            if (msg.what == 101)
                MainActivity.this.textview.setText(msg.getData().getString("toMain").toString());
        }

    };

    1、你对比下,你会发现你handler1  里面的  public void HandleMessage(Message msg) 写错了(你仔细看下),并没有覆盖父类的 handleMessage(Message msg)  
    2、final Message msgReply=handler1.obtainMessage(); 这句话是有问题的。 会报消息复用的异常
写到全局: Message msgReply;
写到 handler2 中的handleMessage(Message msg)方法中   
msgReply = handler1.obtainMessage();
                msgReply.what = 101;
daweibalang717
daweibalang717 我在下面贴了下
4 年多之前 回复

public class MainActivity extends ActionBarActivity {
Button but = null;

TextView textview = null;

Handler handler1, handler2;

Message msgReply;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    but = (Button) super.findViewById(R.id.t1);
    textview = (TextView) super.findViewById(R.id.t2);
    Print p = new Print();

         = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            if (msg.what == 101)
                MainActivity.this.textview.setText(msg.getData().getString("toMain").toString());
        }

    };
    p.start();
    but.setOnClickListener(new OnClickListenerimpl());

}

class Print extends Thread {
    public void run() {

        Looper.prepare();
        handler2 = new Handler() {

            public void handleMessage(Message msg) {
                if (msg.what == 100)
                    System.out.println("接收到了来自主线程的消息");
                msgReply = handler1.obtainMessage();
                msgReply.what = 101;
                Bundle bundle = new Bundle();
                bundle.putString("toMain", "返回的消息");
                msgReply.setData(bundle);
                handler1.sendMessage(msgReply);
            }

        };

        Looper.loop();
    }
}

class OnClickListenerimpl implements OnClickListener {
    public void onClick(View v) {
        if (MainActivity.this.handler2 != null) {
            Message msg = handler2.obtainMessage();
            msg.what = 100;
            handler2.sendMessage(msg);
        }
    }
}

@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;
}

@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);
}

图片说明

 package com.example.threadtest;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    Button button=null;
    TextView textView=null;
    Handler handler1,handler2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.t1);
        textView=(TextView)findViewById(R.id.t2);
        button.setOnClickListener(new OnClickListenerImpl());
        handler1=new Handler(){

            @Override
            public void handleMessage(Message msg) {
                if(msg.what==101){
                    textView.setText(msg.getData().getString("toMain").toString());
                }
                super.handleMessage(msg);
            }

        };
        Print print=new Print();
        print.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 Print extends Thread{
        @Override
        public void run() {
            super.run();
            Looper.prepare();
            handler2=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    if(msg.what==100)
                        System.out.println("接收到来自主线程的消息");
                    Message msgReply=handler1.obtainMessage();
                    msgReply.what=101;
                    Bundle bundle=new Bundle();
                    bundle.putString("toMain", "返回的消息");
                    msgReply.setData(bundle);
                    handler1.sendMessage(msgReply);
                    super.handleMessage(msg);
                }

            };
            Looper.loop();
        }

    }

    class OnClickListenerImpl implements OnClickListener{

        @Override
        public void onClick(View v) {
            if(MainActivity.this.handler2!=null){
                Message msg=handler2.obtainMessage();
                msg.what=100;
                handler2.sendMessage(msg);
            }
        }

    }

}

结果:
图片说明

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐