通过TimerTask从另一个类更新Activity的TextView的两个选项

时间:2014-08-28 19:35:11

标签: java android android-activity textview timertask

首先感谢你的出色工作。论坛对我来说总是很好的帮助,但这次我需要问一个具体的问题。

我创建了一个类Tasks,它将在TextView活动中每秒更新BatteryStatus。我发现有两种方法可以更新文本:

  1. 传递对Context接口的引用
  2. 在活动类
  3. 中创建一个getter函数

    对于解决方案1,我收到此错误:

    09-30 20:08:29.635: W/System.err(14515): android.view.ViewRoot$CalledFromWrongThreadException:      Only the original thread that created a view hierarchy can touch its views.
    

    对于解决方案2,出现此错误:

    09-30 21:23:07.110: W/System.err(16344): java.lang.NullPointerException
    09-30 21:23:07.110: W/System.err(16344): at android.app.Activity.findViewById(Activity.java:1653)
    

    好的,程序不知道TextView的位置和内容。 我需要更改什么才能使其正常工作? 我真的想要了解在另一个类中更新TextViews,Buttons ......的两种方法。

    1. 传递对Context接口的引用:

      public class BatteryStatus extends Activity{
      
          private static Timer myclock;
          private static TimerTask mytask;
          TextView tvBatteryStatus;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
      
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_battery_status);   // XML-Datei im Layout - Ordner
      
              // Text View
              tvBatteryStatus = (TextView) findViewById(R.id.tvBatteryStatus);
      
              // Timer Task
              myclock = new Timer();
              mytask = new Tasks(BatteryStatus.this);
              // schedule the task to run every 1000ms and delay execution for another 1000ms
              myclock.scheduleAtFixedRate(mytask, 1000, 1000);
      
          }
      }
      

      任务

      public class Tasks extends TimerTask  {
      
          Context context;
      
          public Tasks(Context context){this.context = context;}
      
          public void run(){      
              try{Update();}
              catch(Exception e){e.printStackTrace();}
          }
      
          public void Update(){
              TextView txtView = (TextView) ((BatteryStatus)context).findViewById(R.id.tvBatteryStatus);
              txtView.setText("Hello");
          }
      
      }
      
    2. 在活动类

    3. 中创建一个getter函数

      带吸气剂的BatteryStatus

          public class BatteryStatus extends Activity{
      
              private static Timer myclock;
              private static TimerTask mytask;
              TextView tvBatteryStatus;
      
              @Override
              protected void onCreate(Bundle savedInstanceState) {
      
                  super.onCreate(savedInstanceState);
                  setContentView(R.layout.activity_battery_status);   // XML-Datei im Layout - Ordner
      
                  // Text View
                  tvBatteryStatus = (TextView) findViewById(R.id.tvBatteryStatus);
      
                  // Timer Task
                  myclock = new Timer();
                  mytask = new Tasks();
                  // schedule the task to run every 1000ms and delay execution for another 1000ms
                  myclock.scheduleAtFixedRate(mytask, 1000, 1000);
      
              }
      
              public TextView getTextView(){
                  TextView tV = (TextView)findViewById(R.id.tvBatteryStatus);
                  return tV;
              }
      
          }
      

      任务

          public class Tasks extends TimerTask  {
      
              TextView t;
              BatteryStatus b = new BatteryStatus();
      
              public void run(){      
                  try{Update();}
                  catch(Exception e){e.printStackTrace();}
              }
      
              public void Update(){
                  t = b.getTextView();
                  t.setText("hellooo");
              }
      
          }
      

4 个答案:

答案 0 :(得分:1)

快速而肮脏的解决方案:

编辑Tasks类:

    public class Tasks extends TimerTask  {

        TextView t;
        Activity activity;
        BatteryStatus b = new BatteryStatus();

        public void run(){      
            try{Update();}
            catch(Exception e){e.printStackTrace();}
        }

        public void Update(){
            if(activity != null){
                activity.runOnUIThread(new Runnable(){
                    t = b.getTextView();
                    t.setText("hellooo");
                });
            }            
        }
        public void setActivity(Activity a){ // this must be called from the rest of your application
            activity = a;
        }

    }

答案 1 :(得分:1)

使用第二种方法,您将实例化一个新的Activity,而不是使用已初始化TextView的Activity。您必须在构造函数中提供活动的引用。

    public Tasks(BatteryStatus b){this.b = b;}

你可以使用textView。

答案 2 :(得分:1)

android中的基本拇指规则是你只能在主线程上更新视图,因此你得到了异常

 09-30 20:08:29.635: W/System.err(14515): android.view.ViewRoot$CalledFromWrongThreadException:      Only the original thread that created a view hierarchy can touch its views.

它告诉您正在从非UI线程访问视图元素。因此,为了从非UI线程进行视图更改,请参阅此网站并阅读主题部分。它所需要的一切...... http://developer.android.com/guide/components/processes-and-threads.html

答案 3 :(得分:0)

针对您在第二个解决方案中遇到的问题在活动类中创建一个getter函数

您必须通过构造函数传递Context引用。

 public class Tasks extends TimerTask  {

        TextView t;
        BatteryStatus b = new BatteryStatus();

         Context context;
         public Tasks (Context context){
         this.context=context;}

        public void run(){      
            try{Update();}
            catch(Exception e){e.printStackTrace();}
        }

        public void Update(){
             TextView txtView = (TextView) ((Activity)context).findViewById(R.id.tvBatteryStatus);
              txtView.setText("Hello");
        }

    }

并在此类中创建Tasks对象,并将此BatteryStatus活动的上下文传递给Tasks.class

 public class BatteryStatus extends Activity{

        private static Timer myclock;
        private static TimerTask mytask;
        TextView tvBatteryStatus;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_battery_status);   // XML-Datei im Layout - Ordner

        // Text View
        tvBatteryStatus = (TextView) findViewById(R.id.tvBatteryStatus);

        // Timer Task
        myclock = new Timer();
        mytask = new Tasks();
        // schedule the task to run every 1000ms and delay execution for another 1000ms
        myclock.scheduleAtFixedRate(mytask, 1000, 1000);
        // make an object and pass the reference of this activity
        Tasks abc = new Tasks(BatteryStatus .this);
    }



}