我创建了一个自定义ArrayAdapter,它显示了包含图像,文本和数据字段的列表视图,可以通过修改一组全局变量来更新。我可以初始化接口并验证通过更改全局变量我可以更改列表视图,但只能从OnCreate()中更改。因此,我尝试使用notifyDataSetChanged()创建一个每200ms更新listview的线程,但我似乎无法启动该线程。试图调用.start();
会产生一个错误,指出“类型MainActivity的方法start()未定义”。任何帮助将不胜感激。
MainActivity
public class MainActivity extends Activity
{
// Sensor Constants
public static String temperature;
public static String humidity;
public static String lpg;
public static String alcohol;
public static int temperature_int;
public static int humidity_int;
public static int lpg_int;
public static int alcohol_int;
// Layout
ListView listView;
ItemAdapter adapter;
// USB
UsbManager USB_Manager;
UsbDevice Sense;
PendingIntent permission;
IntentFilter filter;
//BroadcastReceiver receiver;
//USBBuffer_s_received_data = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize Interface
Model.LoadModel();
listView = (ListView) findViewById(R.id.listView);
String[] ids = new String[Model.Items.size()];
for (int i= 0; i < ids.length; i++)
{ids[i] = Integer.toString(i+1);}
ItemAdapter adapter = new ItemAdapter(this,R.layout.row, ids);
listView.setAdapter(adapter);
//USB
if ((UsbManager) getSystemService(Context.USB_SERVICE) != null)
{
USB_Manager = (UsbManager) getSystemService(Context.USB_SERVICE);
if (USB_Manager.getDeviceList().values().iterator().next() != null)
{
Sense = USB_Manager.getDeviceList().values().iterator().next();
if ((UsbDevice) getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE) != null)
{
Sense = (UsbDevice) getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE);
}
}
}
// Update Layout
temperature_int = 30; humidity_int = 6; lpg_int = 5000; alcohol_int = 500;
temperature = String.valueOf(temperature_int);
humidity = String.valueOf(humidity_int);
lpg = String.valueOf(lpg_int);
alcohol = String.valueOf(alcohol_int);
Model.LoadModel();
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
GUI_Update();
}
@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;
}
public void GUI_Update()
{
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(200);
Model.LoadModel();
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
catch (InterruptedException e)
{
}
}
}
});
//.start();
}
修改 移动.start()的位置修复了问题,但现在应用程序在启动后立即退出,我不确定原因。这是我得到的错误日志..
12-20 17:22:11.010: D/libEGL(15395): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
12-20 17:22:11.010: D/libEGL(15395): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
12-20 17:22:11.018: D/libEGL(15395): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
12-20 17:22:11.096: D/OpenGLRenderer(15395): Enabling debug mode 0
12-20 17:22:11.369: W/dalvikvm(15395): threadid=11: thread exiting with uncaught exception (group=0x4198ac68)
12-20 17:22:11.377: E/AndroidRuntime(15395): FATAL EXCEPTION: Thread-711
12-20 17:22:11.377: E/AndroidRuntime(15395): Process: com.byrdonatwigge.sense, PID: 15395
12-20 17:22:11.377: E/AndroidRuntime(15395): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:857)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.ViewGroup.invalidateChild(ViewGroup.java:4320)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.View.invalidate(View.java:10942)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.View.invalidate(View.java:10897)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.widget.ImageView.invalidateDrawable(ImageView.java:201)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:344)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.graphics.drawable.Drawable.setVisible(Drawable.java:575)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.widget.ImageView.onDetachedFromWindow(ImageView.java:1243)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.View.dispatchDetachedFromWindow(View.java:12627)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:2585)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.view.ViewGroup.removeAllViewsInLayout(ViewGroup.java:4027)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.widget.AbsListView.resetList(AbsListView.java:1924)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.widget.ListView.resetList(ListView.java:521)
12-20 17:22:11.377: E/AndroidRuntime(15395): at android.widget.ListView.setAdapter(ListView.java:462)
12-20 17:22:11.377: E/AndroidRuntime(15395): at com.byrdonatwigge.sense.MainActivity$2.run(MainActivity.java:445)
12-20 17:22:11.377: E/AndroidRuntime(15395): at java.lang.Thread.run(Thread.java:841)
12-20 17:22:12.127: D/AndroidRuntime(15395): Shutting down VM
12-20 17:22:12.127: W/dalvikvm(15395): threadid=1: thread exiting with uncaught exception (group=0x4198ac68)
12-20 17:22:12.127: I/Process(15395): Sending signal. PID: 15395 SIG: 9
编辑#2 * 更新主题 *
private void GUI_Update()
{
new Thread()
{
public void run()
{
while (true)
{
try
{
runOnUiThread(new Runnable()
{
@Override
public void run()
{
Model.LoadModel();
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
});
Thread.sleep(500);
}
catch (InterruptedException e)
{
}
}
}
}.start();
}
日志
12-20 18:49:49.741: D/dalvikvm(17054): Late-enabling CheckJNI
12-20 18:49:50.085: D/libEGL(17054): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
12-20 18:49:50.092: D/libEGL(17054): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
12-20 18:49:50.100: D/libEGL(17054): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
12-20 18:49:50.186: D/OpenGLRenderer(17054): Enabling debug mode 0
12-20 18:50:09.405: D/AndroidRuntime(17117): Shutting down VM
12-20 18:50:09.405: W/dalvikvm(17117): threadid=1: thread exiting with uncaught exception (group=0x4198ac68)
12-20 18:50:09.405: E/AndroidRuntime(17117): FATAL EXCEPTION: main
12-20 18:50:09.405: E/AndroidRuntime(17117): Process: com.byrdonatwigge.sense, PID: 17117
12-20 18:50:09.405: E/AndroidRuntime(17117): java.lang.NullPointerException
12-20 18:50:09.405: E/AndroidRuntime(17117): at com.byrdonatwigge.sense.MainActivity$2$1.run(MainActivity.java:449)
12-20 18:50:09.405: E/AndroidRuntime(17117): at android.os.Handler.handleCallback(Handler.java:733)
12-20 18:50:09.405: E/AndroidRuntime(17117): at android.os.Handler.dispatchMessage(Handler.java:95)
12-20 18:50:09.405: E/AndroidRuntime(17117): at android.os.Looper.loop(Looper.java:136)
12-20 18:50:09.405: E/AndroidRuntime(17117): at android.app.ActivityThread.main(ActivityThread.java:5081)
12-20 18:50:09.405: E/AndroidRuntime(17117): at java.lang.reflect.Method.invokeNative(Native Method)
12-20 18:50:09.405: E/AndroidRuntime(17117): at java.lang.reflect.Method.invoke(Method.java:515)
12-20 18:50:09.405: E/AndroidRuntime(17117): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:781)
12-20 18:50:09.405: E/AndroidRuntime(17117): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
12-20 18:50:09.405: E/AndroidRuntime(17117): at dalvik.system.NativeStart.main(Native Method)
答案 0 :(得分:0)
您应该在.start()
构造函数的最后)
之前移动Thread
public void GUI_Update()
{
new Thread(new Runnable()
{
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(200);
Model.LoadModel();
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
catch (InterruptedException e)
{
}
}
}
}).start(); // here
这应该让它运行。但是,我不确定你为什么要这样做。每200毫秒更换一次是非常快的,我不确定你打算用这个来完成什么。此外,拥有无限loop
并不是一个好主意。
答案 1 :(得分:0)
您应该将Runnable对象发布到原始线程以实现此目的。
但这是一种更复杂的解决方案。 (仅在由于其他原因而无法保持相同方法时才使用)
请改用TimeTask。它将以更清洁,更简单的方式为您的目的服务。
希望这会有所帮助。
答案 2 :(得分:0)
如果您只是需要安排将来发生的事情,则不需要线程。
一个简单的类,不幸的是不适合你的用例是Android的CountDownTimer
。它允许您安排重复事件,直到达到限制。您可以使用某种无限限制。
另一方面,您可以使用基于Handler
的略微修改的版本。 Handler
可以安排在UI线程中发生的事件。
public abstract class Ticker {
private final long mPeriod;
private final Handler mHandler = new Handler(Looper.getMainLooper());
public Ticker(long period) {
mPeriod = period;
}
public final void start() {
stop();
mHandler.post(mTick);
}
public final void stop() {
mHandler.removeCallbacks(mTick);
}
private final Runnable mTick = new Runnable() {
@Override
public void run() {
mHandler.postDelayed(mTick, mPeriod);
onTick();
}
};
/** Called every period ms */
public abstract void onTick();
}
public class Foo extends Activity {
private Ticker mTicker;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mTicker = new Ticker(200) {
@Override
public void onTick() {
// update things
}
};
mTicker.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
mTicker.stop();
}
}
答案 3 :(得分:0)
如果你想在主线程上运行代码,这是我发现的最简单的解决方案。任何时候你想要更新UI,它都必须在主线程上,否则它将失败或什么都不做。
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// code to run on main thread
}
})