2013-12-21 52 views
0

我创建了一个自定义ArrayAdapter,它显示一个列表视图,其中包含图像,文本和可以通过修改一组全局变量进行更新的数据字段。我可以初始化接口,并验证通过更改全局变量,我可以更改列表视图,但只能从OnCreate()中。因此,我尝试使用notifyDataSetChanged()每200毫秒创建一个线程来更新列表视图,但我似乎无法启动线程。试图呼叫.start();会创建一个错误,指出“方法start()对于MainActivity类型未定义”。任何帮助,将不胜感激。创建一个GUI更新线程

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(); 
    } 

编辑 运动。开始的位置()解决了这一问题,但现在的应用程序会立即退出一经推出,我不知道为什么。这是错误日志,我得到..

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

你应该将.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 

这应该使它运行。不过,我不确定你为什么要这样做。每200ms改变一次速度非常快,我不确定你打算如何完成这个任务。此外,有一个无限的loop很少是一个好主意。

+0

谢谢。你是对的;这只是代码的粗略草案。但是,现在应用程序在启动后立即退出,我不知道为什么。我已经更新了原始日志 – Willis

+0

'MainActivity'的第445行是什么? – codeMagic

+0

445行是:''listView.setAdapter(adapter);'' – Willis

0

您应该将一个Runnable对象发布到原始线程以实现此目的。

但这是一种更复杂的解决方案。 (只有在因其他原因而不能保持相同方法时才使用它)

改为使用TimeTask。它将以更简洁更简单的方式满足您的需求。
希望这会有所帮助。

0

如果您只需要安排将来要发生的事情,则无需线程。

一个简单的类,不幸的是你的用例不完美是Android的CountDownTimer。它允许您安排重复事件,直到达到限制。你可能可以用某种无限的限制来使用它。

另一方面,您可以使用基于Handler的稍作修改的版本。 A 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(); 
    } 
} 
0

如果你想在主线程上运行代码,这是我找到的最简单的解决方案。任何时候你想要更新用户界面,它都必须在主线程上,否则将会失败或者什么都不做。

new Handler(Looper.getMainLooper()).post(new Runnable() { 

    @Override 
    public void run() { 
     // code to run on main thread 
    } 
})