1

我是 Android 新手,发现要不断更新主视图,我必须创建一个线程来处理各种进程,然后将更新传递回主视图。我决定使用 Handler 类来做到这一点。此示例中的视图有一个用于激活代码的按钮和一个用于显示接收到的消息的表格布局 - 代表流程的一个阶段。

问题是我发送了 8 条不同的消息,我可以看到 8 条消息在处理程序中返回,但所有 8 条消息的内容仅与消息 8 相同。

我期待处理程序按顺序接收消息。

任何关于更好的方法的建议总是欢迎学习。

这是代码:

`

public class messageHandlerTest extends Activity {

protected TextView textView;
protected Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            String[] status = (String[]) msg.obj;
            createTableRow(status);
            Log.e("Got a new message",status[0]+":"+status[1]);
        }
    };

Button btnStartProgress;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.statusText);
    textView.setText("");
    //Getting response from server with Network SSID and Password

    Button connectButton = (Button)findViewById(R.id.connectButton);
    addListenerOnButton();
} // End of create

protected class connectWiFi extends Thread implements Runnable {
    //tokens1 = new String[0];
    public void run(){
    try {
        String[] messageString = new String[2];
        Message message = handler.obtainMessage();
        messageString[0]="OK";
        messageString[1]="Number 1";
        message.obj = messageString;
        handler.sendMessage(message);

        message = handler.obtainMessage();
        messageString[0]="OK";
        messageString[1]= "Number 2";
        message.obj = messageString;
        handler.sendMessage(message);
        message = handler.obtainMessage();
        messageString[0]="OK";
        messageString[1] = "Number 3";
        message.obj = messageString;
        handler.sendMessage(message);
        message = handler.obtainMessage();
        messageString[0]="OK";
        messageString[1] = "Number 4";
        message.obj = messageString;
        handler.sendMessage(message);

                    message = handler.obtainMessage();
                    messageString[0] = "OK";
                    messageString[1] = "Number 5";
                    message.obj = messageString;
                    handler.sendMessage(message);

                    message = handler.obtainMessage();
                    messageString[0] = "OK";
                    messageString[1] = "Number 6";
                    message.obj = messageString;
                    handler.sendMessage(message);

                    message = handler.obtainMessage();
                    messageString[0] = "OK";
                    messageString[1] = "Number 7";
                    message.obj = messageString;
                    handler.sendMessage(message);

                    message = handler.obtainMessage();
                    messageString[0] = "OK";
                    messageString[1] = "Number 8";
                    message.obj = messageString;
                    handler.sendMessage(message);

    } catch (Exception e) {
        e.printStackTrace();
        Log.e("Exception found","bugger");
    }
    }// End or run
}// End of class

public void addListenerOnButton() {

    btnStartProgress = (Button) findViewById(R.id.connectButton);
    btnStartProgress.setOnClickListener(
            new OnClickListener() {
                @Override
                public void onClick(View v) {
                connectWiFi connectwifi = new connectWiFi();
                connectwifi.start();
                }

            });

}
private void createTableRow(String[] stage) {
    TableLayout tl = (TableLayout) findViewById(R.id.statusTable);
    TableRow tr = new TableRow(this);
    LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    tr.setLayoutParams(lp);
    tr.setBackgroundColor(0xFFFFFFFF);
    TextView tvStatus = new TextView(this);
    tvStatus.setLayoutParams(lp);
    tvStatus.setPadding(2,1,1,2);
    tvStatus.setTextColor(0xFF000000);
    tvStatus.setText(stage[0]); // Status
    TextView tvStage = new TextView(this);
    tvStage.setLayoutParams(lp);
    tvStage.setPadding(2,1,1,2);
    tvStage.setTextColor(0xFF000000);
    tvStage.setText(stage[1]); // Stage
    tr.addView(tvStatus);
    tr.addView(tvStage);
    tl.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}
@Override
protected void onDestroy() {
    super.onDestroy();
}

}

此代码的结果如下所示:

在此处输入图像描述

4

5 回答 5

8

要通过处理程序发送数据,您可以使用 bundle 作为要发送到处理程序的消息对象的数据。像这样的代码:

// receieve message in handleMessage method of handler of your controller (e.g. on UI thread)
handler = new Handler() { 
    @Override
    public void handleMessage(Message msg) {
        Bundle b = msg.getData();
        Integer value = b.getInt("KEY");
        ...
    }
};

// Sending message in a background thread
new Thread(new Runnable() {
    @Override
    public void run() {
        final Message msg = new Message();
        final Bundle b = new Bundle();
        Integer value = 1;
        b.putInt("KEY", value);
        msg.setData(b);
        handler.sendMessage(msg);    
    }
).start();
于 2014-05-04T07:24:16.767 回答
3

我怀疑可能发生的事情是您不断修改名为 messageString 的相同引用 String[] 而从未创建新引用。通过引用传递它,然后继续更改值,这可能是导致此结果的原因。

一些东西,

  1. 使用处理程序时,请尝试使用 what 字段作为返回码。例如,你的 OK 字符串(如果它只是一个状态)你最好定义 int 常量返回类型。
  2. 正如 JanBo 所提到的,您不想扩展 Thread 并实现 Runnable。
  3. 这实际上取决于您要尝试做什么,但处理程序消息队列回调模式是您可以选择完成您想要的众多模式之一。为了学习另一种方法,请查看我在这里写的一篇博文,它解释了如何将非 UI 线程任务委托给 IntentService 并在它完成时回调您的 Activity。
于 2013-08-16T17:18:17.337 回答
2

I suppose what's happening is that: messageString, which you create only once, is being updated while message is waiting in the queue. Change your code like this:

String[] messageString1 = new String[2];
Message message = handler.obtainMessage();
messageString1[0]="OK";
messageString1[1]="Number 1";
message.obj = messageString1;
handler.sendMessage(message);

String[] messageString2 = new String[2];
message = handler.obtainMessage();
messageString2[0]="OK";
messageString2[1]= "Number 2";
message.obj = messageString2;
handler.sendMessage(message);

....
....
于 2013-08-16T17:19:11.233 回答
1

我不确定我是否在正确的地方这样做,但我想我会根据我在这里收到的帮助发回我重构的代码,它可能会帮助其他人。这对我来说效果很好,代码看起来很整洁,但是任何关于如何改进或提高效率的反馈都将受到赞赏。如果我在错误的地方这样做,也请告诉我!

public class messageHandlerTest2 extends Activity {

protected TextView textView;
protected Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        createTableRow((mymessageObject) msg.obj);
    }
};  //Set-up handler to be used later

Button btnStartProgress;

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

    Button connectButton = (Button) findViewById(R.id.connectButton);
    addListenerOnButton();
} // End of create

protected class connectWiFi extends Thread {
    public void run() {
        try {
            sendMessage(true,"Number 1"); // send if OK and a stage message
            sendMessage(true,"Number 2");
            sendMessage(true,"Number 3");
            sendMessage(true,"Number 4");
            sendMessage(true,"Number 5");
            sendMessage(true,"Number 6");
            sendMessage(true,"Number 7");
            sendMessage(true,"Number 8");
            sendMessage(true,"Number 9");
            sendMessage(true,"Number 10");
            sendMessage(true,"Number 11");
            sendMessage(true,"Number 12");

        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Exception found", "bugger");
        }
    }// End or run
}// End of class

public void addListenerOnButton() {

    btnStartProgress = (Button) findViewById(R.id.connectButton);
    btnStartProgress.setOnClickListener(
            new OnClickListener() {
                @Override
                public void onClick(View v) {
                    connectWiFi connectwifi = new connectWiFi();
                    connectwifi.start();
                }

            });
}

private void createTableRow(mymessageObject stage) {
    String statusString;
    TableLayout tl = (TableLayout) findViewById(R.id.statusTable);
    TableRow tr = new TableRow(this);
    LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    tr.setLayoutParams(lp);
    tr.setBackgroundColor(0xFFFFFFFF);
    TextView tvStatus = new TextView(this);
    tvStatus.setLayoutParams(lp);
    tvStatus.setPadding(2, 1, 1, 2);
    tvStatus.setTextColor(0xFF000000);
    if (stage.Status) {statusString = "OK";} else {statusString = "No";};
    tvStatus.setText(statusString); // Status
    TextView tvStage = new TextView(this);
    tvStage.setLayoutParams(lp);
    tvStage.setPadding(2, 1, 1, 2);
    tvStage.setTextColor(0xFF000000);
    tvStage.setText(stage.statusMessage); // Stage
    tr.addView(tvStatus);
    tr.addView(tvStage);
    tl.addView(tr, new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
}

@Override
protected void onDestroy() {
    super.onDestroy();
}
private class mymessageObject {  // Creates object of status flag and stage message
    boolean Status;
    String statusMessage;
    mymessageObject(boolean newStatus, String newMessage){
        Status = newStatus;
        statusMessage = newMessage;
    }
}
private void sendMessage (boolean status, String stageMessage) { // Handle sending message back to handler

    Message message = handler.obtainMessage();
    message.obj = new mymessageObject(status,stageMessage);
    handler.sendMessage(message);
}

}

于 2013-08-17T10:26:38.540 回答
-2

尝试这个

Message m = Message.obtainMessage();

不是

Message m = handler.obtainMessage();
于 2013-08-16T14:58:03.223 回答