2013-12-21 99 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 
    } 
})