解决'从错误的线程调用'异常

时间:2013-05-09 19:54:33

标签: android timer onclick textview

我的应用程序的目的是:用户输入一个数字并单击一个按钮。该按钮使用输入来计算斐波纳契序列的计时器 - 序列中的每个数字每秒显示一个textView。但是当我尝试运行计时器时,我得到了CalledFromWrongThreadException。我在下面发布了我的代码。正如您可以通过我的日志声明所知,我相信我知道导致问题的是哪一行。我认为这是因为我正在调用一个在我的onclicklistener之外的方法,但当我移动其他方法时,我只会造成更多问题。

我已经阅读了其他一些帖子,我不确定使用我的方法打印到文本区域的正确方法是什么。有谁知道我怎么能做这个工作?

public class MainActivity extends Activity {

// primary widgets
private EditText editText;
private TextView textView;
private Button button1;

static int seconds = 0;
static Timer timer;

static ArrayList<Integer> fibList = new ArrayList<Integer>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editText = (EditText) findViewById(R.id.editText1);
    textView = (TextView) findViewById(R.id.textView2);
    button1 = (Button) findViewById(R.id.button1);

    final int delay = 1000;
    final int period = 1000;
    timer = new Timer();

    //Attempt to clear TextView
    textView.setText("");

    button1.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            //Clear Textview
            String array = " "; 
            fibList.clear();
            textView.setText(array);
            //Log.i("ARRAY", "ATTEMPT to CLEAR"+fibList);

            String input = editText.getText().toString();
            int number = Integer.parseInt(input);
            int tmp = 0;

            // confirm input
            if (number < 20) {
                Toast.makeText(getApplicationContext(),
                        "You entered: " + number, Toast.LENGTH_LONG).show();
                for (int i = 0; i <= number; i++) {
                    fibList.add(fib(i));

                    // sum even numbers
                    if (fib(i) % 2 == 0) {
                        tmp += fib(i);

                    }

                }
            } else {
                Toast.makeText(getApplicationContext(),
                        "Number is too Large: " + number, Toast.LENGTH_LONG)
                        .show();
            }


            //I believe error occurs in this method

             Log.i("TEST", "START TIMER");
             timer.scheduleAtFixedRate(new TimerTask() {

                    public void run() {      
                             Log.i("TEST", "RUN TIMER");
                        int nextIndex = setInterval();
                        Log.i("TEST", "SET INTERVAL");
                          if (nextIndex < fibList.size()) {
                              Log.i("TEST", "TRY TO PRINT");

                              //It looks like error occurs here when I try to print to textView
                              textView.setText(fibList.get(nextIndex)+ " ");
                              Log.i("TEST", "NEXT INDEX"+fibList.get(nextIndex));
                              Log.i("TEST", "DID PRINT");
                          }
                    }
                }, delay, period);
             Log.i("TEST", "END TIMER");

        }

    });

}

// run fibonacci sequence
public static int fib(int n) {
    if (n < 2) {
        return n;
    } else {
        return fib(n - 1) + fib(n - 2);
    }
}

//counts up for every element through the array
    public static final int setInterval() {

        if (seconds >= fibList.size())
            timer.cancel();
        return seconds++;

    }

@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;
}

}

3 个答案:

答案 0 :(得分:1)

您可以使用

runOnUiThread(new Runnable(){
     public void run(){
     textView.setText("aaa"); 
    } 
});

答案 1 :(得分:0)

让您的计时器向处理程序发送消息。默认情况下,处理程序将在主线程上运行。然后,IT可以根据需要更改UI,因此只需将计时器的主体放入该处理程序即可。

答案 2 :(得分:0)

我刚遇到这个问题,然后来到StackOverflow查看解决方案。没有找到任何合适的东西,但是更多的试验有很多日志,调试让我得到了解决方案。

getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
              textView.setText("Your String");                                     
    }                    
});

在我的代码中,问题是由于我使用TextView.post(new Runnable...)一个接一个地在单独的线程中访问两个TextView。我想这是因为它无法访问UI线程(因为它忙于以前的线程更改)。在UI Thread中将两个TextView放在一起解决了这个问题。所以在这里张贴给其他可能被类似问题困扰的人。希望它有所帮助。