-2

I just want my code to display the values 1 to 10 in a listview. However, I want to "simulate" pausetimes by sleeping for 250 milliseconds each time an item is added into the listview. The problem is that calling Thread.sleep() results in a run time crash. The first item (the number 1) displays successfully, but it crashes after that. Any suggestions on why my program crashes?

if I comment out Thread.sleep(), this works

class Read extends AsyncTask<Void, Integer, Void> {
    ArrayAdapter<String> adpt;
    File file;
    Scanner scan;

    Read(ArrayAdapter<String> a, File f) {
        adpt = a;
        file = f;
        try {
            scan = new Scanner(file);
        }
        catch (IOException e) {
            Toast.makeText(MainActivity.this, "Error reading file!", Toast.LENGTH_SHORT).show();
            // I should do something... just not sure what.
        }
    }

    @Override
    protected void onPreExecute() {

    }

    @Override
    protected Void doInBackground(Void... params) {
        Integer i = 0;
        //   Toast.makeText(MainActivity.this, "Error reading file!", Toast.LENGTH_SHORT).show();
        adpt.setNotifyOnChange(false);
        while (scan.hasNext()) {
            String j = scan.next();
            adpt.add("dead");
            i++;
            try {
                Thread.sleep(250);
            }
            catch (InterruptedException e) {
            }
            publishProgress(i);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        adpt.notifyDataSetChanged();
    }

    @Override
    protected void onPostExecute(Void result) {
        scan.close();
        adpt.notifyDataSetChanged();
    }
}

Error Logs

E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
                  Process: com.example.multithread, PID: 4314
                  java.lang.RuntimeException: An error occurred while executing doInBackground()
                      at android.os.AsyncTask$3.done(AsyncTask.java:318)
                      at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
                      at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:242)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                      at java.lang.Thread.run(Thread.java:761)
                   Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
                      at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6855)
                      at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1040)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
                      at android.view.View.requestLayout(View.java:19655)
                      at android.widget.AbsListView.requestLayout(AbsListView.java:1988)
                      at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:840)
                      at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6357)
                      at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
                      at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
                      at android.widget.ArrayAdapter.notifyDataSetChanged(ArrayAdapter.java:310)
                      at android.widget.ArrayAdapter.add(ArrayAdapter.java:200)
                      at com.example.multithread.MainActivity$Read.doInBackground(MainActivity.java:70)
                      at com.example.multithread.MainActivity$Read.doInBackground(MainActivity.java:39)
                      at android.os.AsyncTask$2.call(AsyncTask.java:304)
                      at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                      at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                      at java.lang.Thread.run(Thread.java:761) 
Application terminated.
Cameron
  • 2,805
  • 3
  • 31
  • 45
  • 1
    We need the error message that you get! I thought it would be a nullpointerexception; but assuming that your comment "// set in constructor" is correct, that might not be the reason. But please: turn to the help center and read about "how to ask" ... and then add the information to your question that we need to help you. – GhostCat Oct 31 '16 at 07:15
  • ok. I'll add the constructor too. Where is the "how to ask section" – Cameron Oct 31 '16 at 07:16
  • 1
    Basically you want to study the stuff here: http://stackoverflow.com/help/asking – GhostCat Oct 31 '16 at 07:18
  • Note that this works as long as I comment out the thread.sleep code. – Cameron Oct 31 '16 at 07:23
  • Also, why is everyone downvoting this? What am I even violating? I have a genuine question that I've spent several hours trying to find an answer for. – Cameron Oct 31 '16 at 07:24
  • 1
    Yes, but apparently you didn't think to pay attention to the error message. Certainly this makes the question of little use to other users. Basically, your description of the problem is a red herring. – Stephen C Oct 31 '16 at 07:54

1 Answers1

1

It's not the Thread.sleep() that causes the crash. As seen in the logcat, you're trying to modify an UI component adpt in a non-UI thread.

You can move the adpt.add() call to e.g. onProgressUpdate() to make it execute on the UI thread.

laalto
  • 150,114
  • 66
  • 286
  • 303