2015-02-23 88 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