Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么消息在传递到另一个线程时会丢失其内容?_Java_Android - Fatal编程技术网

Java 为什么消息在传递到另一个线程时会丢失其内容?

Java 为什么消息在传递到另一个线程时会丢失其内容?,java,android,Java,Android,在开发Android应用程序的过程中,我发现(在我看来)一个非常奇怪的行为。 通过将消息对象(android.os.message)传递到另一个线程,它将丢失其所有内容。也许有人能给我解释一下为什么会这样?我编写了一个示例应用程序来说明这个问题: 主要活动: package com.test.bundletest; import android.content.ComponentName; import android.content.Intent; import android.conten

在开发Android应用程序的过程中,我发现(在我看来)一个非常奇怪的行为。 通过将消息对象(android.os.message)传递到另一个线程,它将丢失其所有内容。也许有人能给我解释一下为什么会这样?我编写了一个示例应用程序来说明这个问题:

主要活动:

package com.test.bundletest;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private Messenger mOutMsger;

    private final ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mOutMsger = new Messenger(service);
            System.out.println("Connected");
            sendMultipleMessages(10);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startService(new Intent(this, MyService.class));
        bindService(new Intent(this, MyService.class), mConnection, BIND_AUTO_CREATE);
    }

    private void sendMultipleMessages(int messageCount){
        if (mOutMsger!=null){
            for (int i = 0; i<messageCount; i++){
                Message msg = Message.obtain();
                Bundle b = new Bundle();
                b.putString("test", "Just a test");
                msg.setData(b);
                msg.what = i;
                try {
                    mOutMsger.send(msg);
                    System.out.println("Message sent");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }else {
            System.out.println("Messenger was null");
        }
    }
}
输出:

8751-8751/com.test.bundletest I/System.out: Connected
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out: Message sent
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 0Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 1Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 2Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 3Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 4Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 5Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 6Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 7Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 8Data? - false KeySet size? - 1
8751-8751/com.test.bundletest I/System.out:  UI Thread - What? - 9Data? - false KeySet size? - 1
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
8751-8809/com.test.bundletest I/System.out:  NonUI Thread - What? - 0Data? - true KeySet size? - 0
更奇怪的是,如果我在处理邮件之前复制了邮件,这种情况就不会发生:

package com.test.bundletest;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyService extends Service {

    private ExecutorService mExe = Executors.newSingleThreadExecutor();

    @SuppressLint("HandlerLeak")
    private final Handler mInHandler = new Handler(){
        @Override
        public void handleMessage(final Message msg) {
            System.out.println(
                    new StringBuilder(" UI Thread - What? - ")
                            .append(msg.what)
                            .append("Data? - ")
                            .append(msg.peekData() == null)
                            .append(" KeySet size? - ")
                            .append(msg.getData().keySet().size()));
            final Message msg2 = Message.obtain(msg);
            mExe.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(
                            new StringBuilder(" NonUI Thread - What? - ")
                                    .append(msg2.what)
                                    .append("Data? - ")
                                    .append(msg2.peekData() == null)
                                    .append(" KeySet size? - ")
                                    .append(msg2.getData().keySet().size()));
                }
            });
        }
    };

    private final Messenger mInMessenger = new Messenger(mInHandler);

    @Override
    public IBinder onBind(Intent intent) {
        return mInMessenger.getBinder();
    }
}
以这种方式运行,UI线程和非UI线程的输出是相同的


我的Java知识已经不多了,希望有人能给我解释清楚。

您使用
Message.get()

创建新线程时,方法
handleMessage(Message msg)
完成执行,仍然属于全局池的对象消息正在循环。因此,在新线程中,该对象已为空

在您的服务中,您可以这样做:

@Override
public void handleMessage(Message msg) {
    final Message message = new Message();
    message.copyFrom(msg);
    //your code
}

或者,您可以将
消息
对象映射到您自己的自定义对象中。最好仅使用
消息
对象通过
处理程序进行数据传输

谢谢!似乎正是描述的方式。消息对象在handleMessage(消息消息消息)完成后被回收。如果我延迟方法的结束,数据将被保留。遗憾的是,文档中显然没有描述此过程。
@Override
public void handleMessage(Message msg) {
    final Message message = new Message();
    message.copyFrom(msg);
    //your code
}