2015-02-23 119 views
-1

最近我開始研究家庭監控系統。我正在使用和arduino讀取傳感器數據(如溫度)並通過串口將其發送到樹莓派。在樹莓派上,我正在運行一個Java TCP服務器,它讀取串行數據並將其發送給客戶端(格式:溫度:光照)。這一切都很好,所以昨天我開始開發一個連接到服務器並顯示數據的android應用程序。這部分也工作得很好。但是當我試圖製作一個小部件時,我遇到了一個問題。因爲我需要每1秒更新一次TextViews(或每當接收到數據時),我將RemoteViews,AppWidgetManager和int [] appWidgetIds存儲在一些私有變量中,每次調用onUpdate()方法時都會刷新它們。問題是變量有一個值,但是當我嘗試使用它們是由startListener()方法創建的新線程時,我得到一個NullPointerException。如何在線程之間共享對象

下面的代碼:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.net.Socket; 
import java.net.UnknownHostException; 

import android.appwidget.AppWidgetManager; 
import android.appwidget.AppWidgetProvider; 
import android.content.Context; 
import android.util.Log; 
import android.widget.RemoteViews; 

public class WidgetActivity extends AppWidgetProvider { 

private volatile RemoteViews views; 
private volatile AppWidgetManager manager; 
private volatile int[] ids; 
private volatile Thread listener; 
private volatile boolean running = false; 
private volatile Socket s; 
private volatile BufferedReader br; 

public void onEnabled(Context context){ 
    startListener(); 
} 

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){ 
    views = new RemoteViews(context.getPackageName(), R.layout.activity_widget); 
    Log.d("Views1", views.toString()); 
    manager = appWidgetManager; 
    Log.d("Manager1", manager.toString()); 
    ids = appWidgetIds; 
    Log.d("IDS1", ids.toString()); 
    startListener(); 
} 

public void onDisabled(Context context){ 
    running = false; 
    if(listener != null){ 
     listener.interrupt(); 
    } 
    listener = null; 
    try { 
     if(br != null){ 
      br.close(); 
     } 
     if(s != null){ 
      s.close(); 
     } 
    } catch (IOException e) { 
    } 
} 

public void startListener(){ 
    if(listener == null || !listener.isAlive() || !running){ 
     listener = new Thread(){ 
      public void run(){ 
       synchronized(views){ 
        synchronized(ids){ 
         synchronized(manager){ 
       try { 
        s = new Socket("000.000.000.000", 7777); 
        br = new BufferedReader(new InputStreamReader(s.getInputStream())); 
        running = true; 
        while(running && !this.isInterrupted()){ 
         String data = br.readLine(); 
         if(data != null && data.contains(":")){ 
          String[] split = data.split(":"); 
          if(views != null){ 
           views.setTextViewText(R.id.tempWidget, "Temperature: " + split[0]); 
           views.setTextViewText(R.id.lightWidget, "Light: " + split[1]); 
          }else{ 
           Log.d("Views", "NULL!"); 
          } 
          if(ids != null && manager != null){ 
           for(int id : ids){ 
            manager.updateAppWidget(id, views); 
           } 
          }else{ 
           Log.d("IDS", "NULL!"); 
           Log.d("Manager", "NULL!"); 
          } 
         } 
        } 
        if(br != null){ 
         br.close(); 
        } 
        if(s != null){ 
         s.close(); 
        } 
        listener = null; 
       } catch (UnknownHostException e) { 
       } catch (IOException e) { 
       } 
      } 
      } 
     } 
      } 
     }; 
     listener.start(); 
    } 
} 
} 

我很新的Android和這段代碼是隻是爲了測試通信,並開始學習多一點關於Android。我將重新構建整個應用程序,並在完成該工作後使代碼更加美觀。

感謝您的幫助:)

我試過各種東西了,像synchronized塊和volatile修飾符......似乎沒有任何工作...

+0

爲什麼你有三個同步塊在級聯? – Blackbelt 2015-02-23 13:34:19

+0

@Blackbelt因爲我需要共享所有三個對象。當我在onUpdate方法中顯示它們的值時,值不爲null。但是線程中顯示的值爲空。如果這使得任何意見。 :) – 2015-02-23 13:55:56

回答

1

是否在UI上運行的東西線程可以幫助你..

public void startListener(){ 
    if(listener == null || !listener.isAlive() || !running){ 

     listener = new Thread(){ 

      public void run(){ 

       Handler mHandler = new Handler(); 

       mHandler.post(new Runnable(){ 
        public void run() { 

         //try here 

        } 
       }); 
+0

沒有抱歉,我已經試過了,但它看起來像這個方法不可用在一個小部件。 – 2015-02-23 13:50:44

+0

可以請你再試一次..我更新的答案 – 2015-02-23 14:03:04

+0

嘿,它的工作:)比你! 我只是想知道是否有一個簡單的方法將它發佈到處理程序後停止線程? – 2015-02-23 14:12:23