android - programacion - Cómo programar fuera del hilo principal de UI
manual de programacion android pdf (3)
ui thread es el hilo principal. usted sabe sobre el hilo actual por
Thread.currentThread().getName();
lo siento, no leí toda su pregunta, pero tiene que hacer el proceso de bloqueo en otro hilo que mainThread.
hay muchas formas de hacerlo: AsyncTask, Services, ExecutorService y RxJava. y cuál elegir depende de su necesidad
este enlace sería útil :)
No sé si existe un hilo de UI por defecto, cómo crearlo si no, o cómo decirlo cuando estoy "adentro" donde comienza y termina si es así. ¿Cómo me aseguro de que PacketListener
no sea parte del hilo principal de UI?
Sigo corriendo en esta NetworkOnMainThreadException . Entiendo que eso significa que estoy tratando de hacer algo en el hilo principal de UI que debería tener su propio hilo por separado. Sin embargo, no puedo encontrar mucho que decirme CÓMO hacer eso.
Pensé que la clase MainActivity SERÍA el hilo de UI, ya que, bueno, tenía una IU y funcionó. Sin embargo, he creado una clase separada que implementa Runnable, y coloqué las conexiones de red allí, y aún recibo la excepción, por lo que sigue siendo parte del hilo principal, ¿sí? Puedo ver que MainActivity no extiende Thread, así que tal vez fue una suposición tonta. No tengo la sensación de que algo cambie si agrego otra clase que implemente Runnable / extends Thread. ¿Lo hará?
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();
}
}
}
EDITAR:
Mi último intento, tratando de seguir el ejemplo de esta página , ha seguido la ruta de la mayoría de mis intentos y rompí la aplicación por completo. SendAnother
es un método de prueba vinculado a un botón:
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");
}
});
}
});
}
Creo que la próxima vez probaré AsyncTask
. Ya no me importa mucho si está "sucio".
Su último método es correcto, excepto que el hilo aún no se ha iniciado. Entonces debes llamar al 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();
}
Todavía no estoy seguro de que me guste AsyncTask para este proyecto, así que si alguien puede ofrecer consejos o un enlace a un tutorial para usar Handler o Runnable, ¡POR FAVOR publíquelo!
Estrictamente hablando, esto al menos finalmente me permite hacer cosas fuera del hilo de UI, y esa era la pregunta. Entonces, por lo que vale la pena para los demás que tienen este problema, esto es lo primero que funcionó para mí.
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;
}
}
}