我不知道默认情况下是否存在UI线程,如果不是,如何创建它,或者如何告诉我在" m""它它开始和结束的地方,如果是这样的话。如何确保PacketListener
不是主要UI线程的一部分?
我一直在遇到 NetworkOnMainThreadException 。我理解这意味着我试图在主UI线程中做一些应该有自己独立线程的东西。但是,我无法告诉我如何实际做到这一点。
我原以为MainActivity类会成为UI线程,因为我有一个UI而且它有效。但是,我创建了一个单独的类来实现Runnable,并将网络连接的内容放在那里,我仍然得到异常,所以它仍然是主线程的一部分,是吗?我可以看到MainActivity并没有扩展Thread,所以这可能是一个愚蠢的假设。如果我添加另一个实现Runnable / extends Thread的类,我感觉不会有任何改变。会吗?
MainActivity.java
public class MainActivity extends AppCompatActivity {
ArrayList<String> listItems;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listItems = new ArrayList<>();
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, listItems);
ListView listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(adapter);
(new Thread(new PacketListener(adapter))).run();
}
}
PackageListener.java:
public class PacketListener implements Runnable {
ArrayAdapter<String> adapter;
public PacketListener(ArrayAdapter<String> adapter) {
this.adapter = adapter;
}
public void run() {
byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
DatagramSocket socket = new DatagramSocket();
socket.receive(packet);
}
catch(Exception e) {
adapter.add("Exception: " + e.toString() );
e.printStackTrace();
}
catch(Error e) {
adapter.add("Unspecified Error: " + e.toString() );
e.printStackTrace();
}
}
}
我最近的尝试,尝试按照this page's示例,已经走了大部分尝试的路线,并完全打破了应用程序。 SendAnother
是绑定到按钮的测试方法:
public void sendAnother(View view) {
adapter.add("button clicked");
new Thread(new Runnable() {
public void run() {
listview.post(new Runnable() {
public void run() {
adapter.add("inside worker thread");
}
});
}
});
}
我想下一步我终于会尝试AsyncTask
。我不再在乎它是否肮脏&#34;。
答案 0 :(得分:1)
ui线程是主线程。
你知道当前的线程Thread.currentThread().getName();
抱歉,我没有阅读你的整个问题但你必须在另一个线程中阻止proccess而不是mainThread。
有很多方法可以做到这一点:AsyncTask,Services,ExecutorService和RxJava。 哪一个选择取决于你的需要
this link会有所帮助:)
答案 1 :(得分:0)
您的上一个方法是正确的,但线程尚未启动。所以你需要调用start()
:
public void sendAnother(View view) {
//adapter.add("button clicked");
new Thread(new Runnable() {
public void run() {
listview.post(new Runnable() {
public void run() {
adapter.add("inside worker thread");
}
});
}
}).start();
}
答案 2 :(得分:0)
我仍然不确定我喜欢这个项目的AsyncTask,所以如果有人可以提供建议或教程链接以使用Handler或Runnable,请发布它!
严格来说,这至少最终让我在UI线程之外做了一些事情,这就是问题所在。 Sooo,对于任何有这个问题的人来说,它的价值在哪里,这是我最初的工作。
public class MainActivity extends AppCompatActivity {
ArrayAdapter<String> adapter;
private static final int PORT= 8888;
private static final int TIMEOUT_MS = 500;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> listItems = new ArrayList<>();
ListView listview = (ListView) findViewById(R.id.lvMain);
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listItems);
listview.setAdapter(adapter);
UpdateView task = new UpdateView();
task.execute();
//just to show these parts are in different threads
String temp = Thread.currentThread().getName();
adapter.add("onCreate: " + temp);
}
private class UpdateView extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
//just to show these parts are in different threads
String temp = Thread.currentThread().getName();
adapter.add("UpdateView: " + temp);
byte[] buf = new byte[256];
byte[] ipAddress = {(byte)192,(byte)168,0,1};
try {
InetAddress address = InetAddress.getByAddress(ipAddress);
String message = "\"xyz\"";
DatagramSocket socket = new DatagramSocket(PORT);
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), address, PORT);
socket.send(packet);
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
}
catch(IOException e) {
adapter.add("IO Exception: " + e.toString() );
e.printStackTrace();
}
adapter.notifyDataSetChanged();
return 0L;
}
}
}