Android 在 Fragment 的 onCreate() 中创建的处理程序未在 UI 线程上执行 handleMessage()
Android Handler created in Fragment's onCreate() not executing handleMessage() on UI thread
在我的片段中:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Handler uiHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
String text = data.getString("event");
mTextView.setText(text);
}
};
server = new ServerClass(uiHandler);
在 onCreateView() 中我设置了 mTextView。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
mTextView = (TextView) v.findViewById((R.id.event));
}
ServerClass相关部分:
public class ServerClass {
private Handler mHandler;
public GameServer(Handler handler) {
mHandler = handler;
}
public void startServer(final int server_port) {
serverThread = new Thread(new Runnable() {
@Override
public void run() {
Socket socket = null;
Bundle data;
Message msg;
try {
serverSocket = new ServerSocket(server_port);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
data = new Bundle();
data.putString("event", "new connection");
msg = new Message();
msg.setData(data);
mHandler.handleMessage(msg);
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
});
serverThread.start();
}
}
我的理解是,由于处理程序是在 UI 线程中创建的 - 在 Fragment 的 onCreate() 中 - 该处理程序中的 handleMessage() 也应该在 UI 线程上执行,但这并没有发生。当我建立新连接时,出现以下错误:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
跟踪堆栈跟踪的其余部分最终指向包含 handleMessage() 中 mTextView.setText(text);
的行作为原因。
我尝试过使用 getMainLooper 设置处理程序,但这没有帮助:
Handler mHandler = new Handler(Looper.getMainLooper()){
// ...
我也试过在 onCreateView() 中创建处理程序,但仍然遇到同样的错误。
请告诉我,我遗漏了一些明显的东西,这让我抓狂。
Only the original thread that created a view hierarchy can touch its
views.
因为使用来自非ui线程的处理程序对象调用handleMessage
方法。
要从非 ui 线程发送消息,请使用 Handler.sendMessage
方法:
Message msg = mHandler.obtainMessage();
data = new Bundle();
data.putString("event", "new connection");
msg.setData(data);
mHandler.sendMessage(msg);
在我的片段中:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Handler uiHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
Bundle data = msg.getData();
String text = data.getString("event");
mTextView.setText(text);
}
};
server = new ServerClass(uiHandler);
在 onCreateView() 中我设置了 mTextView。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_main, container, false);
mTextView = (TextView) v.findViewById((R.id.event));
}
ServerClass相关部分:
public class ServerClass {
private Handler mHandler;
public GameServer(Handler handler) {
mHandler = handler;
}
public void startServer(final int server_port) {
serverThread = new Thread(new Runnable() {
@Override
public void run() {
Socket socket = null;
Bundle data;
Message msg;
try {
serverSocket = new ServerSocket(server_port);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
data = new Bundle();
data.putString("event", "new connection");
msg = new Message();
msg.setData(data);
mHandler.handleMessage(msg);
} catch (IOException e) {
e.printStackTrace();
break;
}
}
}
});
serverThread.start();
}
}
我的理解是,由于处理程序是在 UI 线程中创建的 - 在 Fragment 的 onCreate() 中 - 该处理程序中的 handleMessage() 也应该在 UI 线程上执行,但这并没有发生。当我建立新连接时,出现以下错误:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
跟踪堆栈跟踪的其余部分最终指向包含 handleMessage() 中 mTextView.setText(text);
的行作为原因。
我尝试过使用 getMainLooper 设置处理程序,但这没有帮助:
Handler mHandler = new Handler(Looper.getMainLooper()){
// ...
我也试过在 onCreateView() 中创建处理程序,但仍然遇到同样的错误。
请告诉我,我遗漏了一些明显的东西,这让我抓狂。
Only the original thread that created a view hierarchy can touch its views.
因为使用来自非ui线程的处理程序对象调用handleMessage
方法。
要从非 ui 线程发送消息,请使用 Handler.sendMessage
方法:
Message msg = mHandler.obtainMessage();
data = new Bundle();
data.putString("event", "new connection");
msg.setData(data);
mHandler.sendMessage(msg);