[英]Continuously updating GUI in java Android
我是Eclipse for Android平台上的新Java程序员。 我正在开发一个Android应用程序,它将通过wifi接口接收多播数据,并在TextView中显示该数据。 数据将每1秒更新一次。
我有下面的代码。 但是我在更新GUI时遇到问题。在此代码中,网络接收和gui在同一线程(即主线程)中完成,这就是我的应用程序挂起的原因。
我曾经尝试过使用AsynchTask,但由于我不知道该如何使用它而无法成功。
package com.example.cdttiming;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.Menu;
import android.widget.EditText;
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText Seconds;
Seconds =(EditText)findViewById(R.id.Seconds);
WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wm.createMulticastLock("mydebuginfo");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
InetAddress ia = null;
byte[] buffer = new byte[65535];
MulticastSocket ms = null;
int port = 4321;
try
{
ia = InetAddress.getByName("226.1.1.1");
DatagramPacket dp = new DatagramPacket(buffer, buffer.length,ia,port);
ms = new MulticastSocket(port);
ms.setReuseAddress(true);
ms.joinGroup(ia);
while (true)
{
ms.receive(dp);
String s = new String(dp.getData(),0,dp.getLength());
Seconds.setText(s);
}
}
catch (UnknownHostException e)
{
Seconds.setText(e.getMessage());
}
catch (IOException e)
{
Seconds.setText(e.getMessage());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
谁能告诉我如何使用以上代码,以便我每秒都能接收到数据并将其显示在TextView中?
预先谢谢大家
AsyncTask
并不真正适合您的用例。 如果后台任务需要连续运行,则最好启动一个新线程。 在线程中,使用处理程序将值传达给UI。 在处理程序的回调方法中,您可以更新gui。
有关处理程序的更多信息:
http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
http://developer.android.com/reference/android/os/Handler.html
或谷歌的好例子,以使这一点。
编辑:
好的,您需要做的是启动一个新线程,然后在run方法中放入从套接字读取的部分。 您可以像在内部类中一样创建线程,类似于:
class SocketThread extends Thread {
private final Handler mHandler;
private final WifiManager mWifiManager;
SocketThread(Handler handler, WifiManager wifiManager) {
mHandler = handler;
}
@override public void run() {
// socket code goes here
// whenever you receive a part that should update the ui,
// do something like:
final String s = new String(dp.getData(),0,dp.getLength());
mHandler.post(new Runnable() {
@override
public void run() {
update(s);
}
});
}
}
然后在onCreate()
创建一个处理程序和该线程的实例并启动它。
...
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText Seconds;
Seconds =(EditText)findViewById(R.id.Seconds);
WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
Handler handler = new Handler();
SocketThread thread = new SocketThread(handler, wm);
thread.start();
...
还要在您的活动中定义方法更新。 在这里,您将收到要设置的文本。 此方法将如下所示:
public void update(String s) {
Seconds.setText(s);
}
我建议您将seconds变量( edittext
) edittext
为全局类变量。 这样,您可以从update方法写入它,而不findById
。
我对您的代码进行了一些编辑,这可能与wifi代码有关。 我对框架的这一部分不熟悉。 但是我可以想象它与WifiManager
和连接到它有关。 如果这不起作用,请设置一个断点并逐步执行它,您将看到它在哪里停止执行任何操作。
package com.example.timing;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
EditText Seconds;
String s;
Button button;
byte[] buffer = new byte[65535];
InetAddress ia = null;
int port = 4321;
DatagramPacket dp = new DatagramPacket(buffer, buffer.length,ia,port);
MulticastSocket ms = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Seconds = (EditText) findViewById(R.id.et_time);
WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
Handler handler = new Handler();
SocketThread thread = new SocketThread(handler, wm);
thread.start();
}
class SocketThread extends Thread {
private final Handler mHandler;
SocketThread(Handler handler, WifiManager wifiManager) {
mHandler = handler;
}
@Override
public void run() {
// socket code goes here
try {
wm.setWifiEnabled(true);
WifiManager.MulticastLock multicastLock = wm.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
ia = InetAddress.getByName("226.1.1.1");
ms.setReuseAddress(true);
ms.joinGroup(ia);
while(true) {
ms.receive(dp);
s = new String(dp.getData(),0,dp.getLength());
update(s);
}
} catch (UnknownHostException e) {
update(e.getMessage());
} catch (IOException e) {
update(e.getMessage());
}
}
}
public void update(String s)
{
Seconds.setText(s);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
您不应将AsyncTask用于更长时间的活动-而是使用简单的线程和处理程序。 在该线程中,您进行WI-FI处理(基本上是while(true)循环),并且每当要更新UI时,就将消息传递给Handler并在UI线程中处理该消息。
有关更多信息,请阅读Android开发者博客中著名的无痛线程文章。
您也可以学习适用于Android的Firebase。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.