1

Please answer like you'd teach an amateur. I saw a few answers but unfortunately I do not understand where to insert the code. Here's my code. How do I make this "results1" TextView update every time the for loop runs? Currently, the output displays only when the loop ends. Please remember that I am a beginner. So, clarity please.

I have a

public class MainActivity extends Activity {
    LinearLayout layout1; 
    //One text view, buttons and EditText fields 
}

Then, I have;

 private OnClickListener test = new OnClickListener() {
    @Override
    public void onClick (View V)
    {
        results1.setText("Done");
        results1.append("\n");

        try {
            for(int k=x[1];k<=x1[1];k++) {
                //Bunch of code

                BufferedReader reader = new BufferedReader(new InputStreamReader(
                        process.getInputStream()));

                int j;
                char[] buffer = new char[4096];
                StringBuffer output = new StringBuffer();
                while ((j = reader.read(buffer)) > 0)
                    output.append(buffer, 0, j);
                reader.close();

                str = output.toString();
                Log.d("1:str", str);
                results1.setTextAppearance(getApplicationContext(), 0);
                results1.setTextSize(14);
                results1.setBackgroundColor(Color.rgb(234,234,234));
                results1.setTextColor(Color.parseColor("#00BFFF"));
                results1.append(str);
                results1.append("\n");
                //results1.setTextIsSelectable(true);

            }

        } catch (ArrayIndexOutOfBoundsException e) {
            results1.append(str1);
            System.err.println("ArrayIndexOutOfBoundsException: " + e.getMessage());
        } 
    }
 }; 
 }
codePG
  • 1,754
  • 1
  • 12
  • 19
Zac1
  • 208
  • 7
  • 34

3 Answers3

0

Running this sort of code in the main UI thread is not a good idea and could cause the thread to hang. You should use an AsyncTask to run your heavier processing. When you want to update the UI, you can utilize the onProgressUpdate() method.

JstnPwll
  • 8,585
  • 2
  • 33
  • 56
  • Hi, If you're free, can you please help with restructuring this code? I've never done multi-threading. – Zac1 Nov 27 '14 at 05:39
  • Please use the code I have above as an example... I am looking at other examples on the web to understand better but can't seem to grasp it. Thanks. – Zac1 Nov 27 '14 at 06:28
0

Write an async class like this

public class ReadStreamTask extends AsyncTask<String,Integer,String> {

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
         results1.setText("Done");
         results1.append("\n");
    }

    @Override
    protected String doInBackground(String... link) {
        // TODO Auto-generated method stub


        try {

            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    process.getInputStream()));

            int j;
            char[] buffer = new char[4096];
            StringBuffer output = new StringBuffer();
            while ((j = reader.read(buffer)) > 0)
                output.append(buffer, 0, j);
            reader.close();

           // str += output.toString();

            return output.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return output.toString();
        }

    }

    @Override
    protected void onPostExecute(String result) {
        results1.setText(result);
    }
}

then call that class

new ReadStreamTask.execute();

the three parameters in asynctask (if I'm not wrong)

  • 1st: use this if you want to pass a value to async class(ex String(your url)
  • 2nd: a passed value to async class, usually an integer used when a progress happend to your background task. its value is used to increment a progress but is rarely used.
  • 3rd: most important, is the return type of async class
Pang
  • 9,564
  • 146
  • 81
  • 122
MetaSnarf
  • 5,857
  • 3
  • 25
  • 41
  • Thanks. I have another related question.. please take a look. Thanks: http://stackoverflow.com/questions/27198413/how-to-display-the-ping-output-line-by-line-android-java – Zac1 Nov 29 '14 at 03:52
  • http://stackoverflow.com/questions/27197837/in-asynctask-how-to-pass-data-from-doinbackground-to-main-ui-instantly-and-n – Zac1 Nov 29 '14 at 07:25
0

If you want to make this "results1" TextView update every time the for loop runs, you may put the following AsyncTask as your inner class and call

[YOUR_VIEW].setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                new ReadTask().execute();
            }
});

ReadTask.java

public class ReadTask extends AsyncTask<Void, String, Void>{
        BufferedReader reader = null;
        @Override
        protected void onPreExecute() {
            results1.setText("Done");
            results1.append("\n");
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                  for(int k=x[1];k<=x1[1];k++) {
                    //Bunch of code

                    reader = new BufferedReader(new InputStreamReader(
                            process.getInputStream()));

                    int j;
                    char[] buffer = new char[4096];
                    StringBuffer output = new StringBuffer();
                    while ((j = reader.read(buffer)) > 0)
                        output.append(buffer, 0, j);
                    reader.close();

                    str = output.toString();
                    Log.d("1:str", str);
                    publishProgress(str);

                    //Sleeping for a second
                    try {
                        Thread.sleep(1000);         
                    } catch (InterruptedException e) {
                       e.printStackTrace();
                    }
                    //results1.setTextIsSelectable(true);

                }

            } catch (ArrayIndexOutOfBoundsException e) {
                results1.append(str);
                System.err.println("ArrayIndexOutOfBoundsException: " + e.getMessage());
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  finally {
                try {

                    if (reader != null) {

                        reader.close();
                    }

                } catch (IOException ex) {

                    ex.printStackTrace();

                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            results1.setTextAppearance(getApplicationContext(), 0);
            results1.setTextSize(14);
            results1.setBackgroundColor(Color.rgb(234,234,234));
            results1.setTextColor(Color.parseColor("#00BFFF"));
            results1.append(str);
            results1.append("\n");
            super.onProgressUpdate(values);
        }

    }

Please check if this helps you.

jstn
  • 504
  • 4
  • 14
  • Thank you very much! It works. 1) There can be multiple public classes? (in this case, MainActivity and ReadTask?) That's new to me. 2) In my logCat, I constantly get a msg (TID:522, tag: Parcel, Text: Reading a NULL string not supported here) - what does this mean? – Zac1 Nov 27 '14 at 18:46
  • Also, please tell me what's the purpose of making it sleeping for 1 second? Does this mean we are sending the output of "str" to the publish progress, every one second? (But, on my app, it's not 1 sec, it is output every time the loop finishes) , so what's the purpose of 1 second sleep? Please explain. Thanks again. – Zac1 Nov 27 '14 at 18:49
  • Also, I have a cancel button on the MainActivity. How to stop this AsyncTask when the user presses the cancel button? – Zac1 Nov 27 '14 at 19:23
  • I put 1 second delay to show you the way the TEXTVIEW get updated. Thats it! – jstn Nov 28 '14 at 04:21
  • We need to implement two things to stop or cancel an AsyncTask execution. 1. call cancel() method of AsyncTask from where you want to stop the execution, may be based on the button click. if([YOUR_ASYNC_TASK].getStatus() == Status.RUNNING){ [YOUR_ASYNC_TASK].cancel(true); } 2. check whether the AsyncTask is cancelled or not by using isCancelled() method inside the doInBackground method. protected Object doInBackground(Object... x) { while (/* condition */) { ... if (isCancelled()) break; } return null; } – jstn Nov 28 '14 at 04:22
  • I did that, but unfortunately, I am getting a Null Pointer exception thrown somewhere when i create an object out of this AsyncTask class. More details on my other question, please take a look: http://stackoverflow.com/questions/27179026/boolean-value-does-not-change-on-clicking-cancel-button-how-to-stop-asynctask – Zac1 Nov 28 '14 at 04:35
  • Did you check whether the readTask is running or not on your cancel button click? if(readTask.getStatus() == Status.RUNNING){ readTask.cancel(true); } Check this link, it may help you for sure http://stackoverflow.com/questions/14279695/cant-cancel-async-task-in-android – jstn Nov 28 '14 at 04:48
  • The App does not even start. There's a FATAL EXCEPTION in main. So, I am not able to view any logs. I did add the line "if(readTask.getStatus() == Status.RUNNING){readTask.cancel(true); }" in my cancel button's onClick. – Zac1 Nov 28 '14 at 04:51
  • Can you please checkout my new question. I have another question on how to instantly update values from AsyncTask to the UI. Here's the link: http://stackoverflow.com/questions/27197837/in-asynctask-how-to-pass-data-from-doinbackground-to-main-ui-instantly-and-n – Zac1 Nov 29 '14 at 07:24