2014-01-14 29 views
1

我试图做一个简单的小程序,每秒会增加一个数字。在这种情况下,我正在实现一个应该每秒循环一次的线程,并在每次循环时将“土豆”加1。这工作正常,直到它回到显示方法potatoDisp()。出于某种原因,这会导致我的应用程序崩溃。从run()中删除potatoDisp()可以解决问题,但显示不会随着“马铃薯”的增加而更新。在run()中,如何在没有我的应用程序崩溃的情况下调用方法(Java/Android)?

public int potato = 0; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    potatoDisp(); 
    start(); 
} 

public void potatoDisp() { 
    TextView text = (TextView) findViewById(R.id.textView1); 
    text.setText("You currently have " + potato + " potatoes"); 
} 

public void start() { 
    Thread thread = new Thread(this); 
    thread.start(); 
} 

@Override 
public void run() { 
    while (true) { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      return; 
     } 
     potato++; 
     potatoDisp(); 
    } 
} 

我这样做的Android应用程序,如果有帮助。我尝试过寻找答案,但是当谈到正确的工作线程方式时,我很迷茫。

+1

哦,那些土豆!从崩溃中发布你的logcat。 – codeMagic

+0

你为什么重写主要活动中的运行方法?你有没有尝试在单独的线程中运行你的计数器? – sager89

+0

现在,不要忘记logcat,但将来你应该发布它。这通常会帮助我们更轻松地帮助你。看到我的答案。 – codeMagic

回答

0

您可能会在后台更新UI时发生异常。因为potatoDisp();是从背景Thread调用的,但该函数更新了UI它会给你带来问题。您需要拨打电话runOnUiThread()

@Override 
public void run() { 
while (true) { 
    try 
    { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     return; 
    } 
    potato++; 
    runOnUiThread(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      potatoDisp(); 
     } 
    }); 
    } 
} 

像这样的东西应该工作。

+1

请参阅http://developer.android.com/guide/components/processes-and-threads。html –

+0

谢谢!这正是我所期待的。 –

+0

不客气,很高兴我能提供帮助。良好的资源,@EricWoodruff – codeMagic

2

都需要这样一个可运行/处理器:

private Runnable potatoRun = new Runnable() { 
    @Override 
    public void run() { 
     potatoDisp(); 
    } 
}; 

然后更改

potatoDisp(); 

到:

runOnUiThread(potatoRun); 

当你不在你不能更新视图在UI线程上。

0

问题是您尝试更新除主UI线程之外的线程上的UI(调用text.setText(...))。

虽然我会建议使用TimerTask而不是调用Thread.sleep(...),但有两种主要方法可以编辑当前代码以按预期工作。

- 使用Handler

定义Handler类,将接受的消息,并根据需要更新您的UI。例如:

private final String POTATO_COUNT = "num_potatoes"; 

Handler handler = new Handler() { 
    public void handleMessage(Message msg) { 
     int numPotatoes = msg.getData.getInt(POTATO_COUNT); 
     mText.setText("You currently have " + numPotatoes + " potatoes"); 
    } 
} 

然后在你的代码,你想打电话给你的处理程序来更新您的文本视图,您是否是在主UI线程上执行以下操作:

Bundle bundle = new Bundle(); 
bundle.putInt(POTATO_COUNT, potato); 

Message msg = new Message(); 
msg.setData(bundle); 
handler.sendMessage(msg); 

- - 呼叫runOnUiThread(...)

@Override 
public void run() { 
    while (true) { 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      return; 
     } 
     potato++; 
     runOnUiThread(new Runnable() 
     { 
      public void run() 
      { 
       potatoDisp(); 
      } 
     } 
    } 
} 
+1

*注意*:尽管您不可能在更新之间暂停1秒时遇到问题,但此处(和其他解决方案中)的runOnUiThread示例包含更新UI的主线程与另一个线程更新马铃薯计数器。 'Handler'方法(或者'potatoDisp'接受马铃薯数的int值)可以解决这个问题。 – Yjay

0

,我认为你应该使用异步任务更新从一个线程的UI:http://developer.android.com/reference/android/os/AsyncTask.html

+0

这应该可能是一条评论。虽然可以在这里使用'AsyncTask',但OP执行的方式应该没问题,他们只需要包含'runOnUiThread()'。另外,'AsyncTask'可能是用于计算和更新单个'TextView'的矫枉过正。 – codeMagic

+0

但是,为什么不使用内置的能力来运行一个线程,它将更新也处理线程池的UI,并且(希望)不会导致任何应用程序滞后? http://stackoverflow.com/questions/9296539/android-runonuithread-vs-asynctask – 2014-01-14 20:55:59

相关问题