0

I have a problem with my code, I'm really new to the Android world and I need help with the AsyncTask class...

I have an method supposed to search lines in a CSV file, then regarding how much lines it did found it's supposed to add specific lines to TableLayout thanks to a Map indicating what views to add and in what order to add them.

The method is working as I want but the problem is due to the computing it is freezing my application and I want to do something to indicate to the user that something's happening.

I read something about using AsyncTask but I know that AsyncTask is doing computing in a background thread and that you can't update UI through background thread

Hope you'll understand me (I'm French so my english is approximative ^^)

Here's my code :

private void addModifLinesToView(TableLayout view, String ressource, Map<String,Object> ViewVal, List<List<View>> listeViews) throws IOException {
    try {
        CSVFile csvBT = new CSVFile(new FileInputStream(Environment.getExternalStorageDirectory()+"/"+folder_main+"/"+imported_data+"/"+ressource));
        List<String[]> tableauVals = csvBT.findLines(indicePoste.getText().toString());
        int numLigne = 0;

        //pour chaque ligne trouvée dans le csv
        for (String[] s : tableauVals) {
            numLigne++;
            if (view.getId() == tableauBT.getId())
            {
                numLigneBT++;
            }
            List<View> actualViews = new ArrayList<>();
            List<View> dividers = new ArrayList<>();
            TableRow row = new TableRow(getApplicationContext());
            row.setLayoutParams(new TableLayout.LayoutParams(
                    TableLayout.LayoutParams.MATCH_PARENT,
                    TableLayout.LayoutParams.WRAP_CONTENT));

            //creation des separateurs
            for (int i = 0; i < ViewVal.size()+1; i++) {
                View divider = new View(getApplicationContext());
                divider.setLayoutParams(new TableLayout.LayoutParams(
                        TableLayout.LayoutParams.MATCH_PARENT,
                        TableLayout.LayoutParams.MATCH_PARENT));
                divider.setBackgroundColor(Color.BLACK);
                dividers.add(divider);
            }

            //delimiter a gauche de la ligne
            row.addView(dividers.get(0),
                    new TableRow.LayoutParams(
                            TableRow.LayoutParams.MATCH_PARENT,
                            TableRow.LayoutParams.MATCH_PARENT));

            ArrayList<String> listeModeles;

            for ( Map.Entry<String,Object> entry : ViewVal.entrySet()) {
                if (entry.getKey().contains("EditText")) {
                    EditText et = new EditText(getApplicationContext());
                    actualViews.add(et);
                    et.setMaxWidth(0);
                    et.getBackground().mutate().setColorFilter(getResources().getColor(android.R.color.darker_gray), PorterDuff.Mode.SRC_ATOP);
                    et.setHighlightColor(getResources().getColor(R.color.gris));
                    et.setPadding(3, 3, 3, 7);
                    et.setGravity(Gravity.CENTER);
                    et.setTextColor(Color.BLACK);
                    et.setSingleLine();
                    et.setInputType((int) entry.getValue());
                    et.setImeOptions(EditorInfo.IME_ACTION_DONE);
                    //pour mettre la taiile du text en SP
                    et.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                } else if (entry.getKey().contains("Spinner")) {
                    Spinner spin = new Spinner(getApplicationContext());
                    actualViews.add(spin);
                    spin.getBackground().setColorFilter(getResources().getColor(R.color.noir), PorterDuff.Mode.SRC_ATOP);
                    spin.setPadding(3, 3, 3, 3);
                    spin.setGravity(Gravity.CENTER);
                    spin.setPopupBackgroundResource(R.color.blanc);
                    ByteArrayInputStream bais = new ByteArrayInputStream((byte[])entry.getValue());
                    listeModeles = listerModeles(bais);
                    ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_spinner_item, listeModeles);
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    spin.setAdapter(adapter);
                } else if (entry.getKey().contains("TextView"))
                {
                    TextView tv = new TextView(getApplicationContext());
                    actualViews.add(tv);
                    tv.setText(Integer.toString(numLigne));
                    tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                    tv.setMaxWidth(0);
                    tv.setPadding(3, 3, 3, 7);
                    tv.setGravity(Gravity.CENTER);
                    tv.setTextColor(Color.BLACK);
                    tv.setSingleLine();
                }
            }

            for (int j = 0; j < actualViews.size(); j++) {
                row.addView(actualViews.get(j),
                        new TableRow.LayoutParams(
                                TableRow.LayoutParams.MATCH_PARENT,
                                TableRow.LayoutParams.MATCH_PARENT, 1f));
                row.addView(dividers.get(j + 1),
                        new TableRow.LayoutParams(
                                TableRow.LayoutParams.MATCH_PARENT,
                                TableRow.LayoutParams.MATCH_PARENT));
            }

            view.addView(row);
            //separateur horizontal
            View dividerH = new View(getApplicationContext());
            dividerH.setLayoutParams(new TableLayout.LayoutParams(
                    TableLayout.LayoutParams.MATCH_PARENT,
                    3));
            dividerH.setBackgroundColor(Color.BLACK);
            view.addView(dividerH, new TableLayout.LayoutParams(
                    TableLayout.LayoutParams.MATCH_PARENT,
                    3));
            listeViews.add(actualViews);
        }
    }
    catch (ArrayIndexOutOfBoundsException | FileNotFoundException e) {
        e.printStackTrace();
    }
}
Reaperino
  • 145
  • 8
  • 2
    You said you are doing computation in AsyncTask, then why your application is freezing. – Amit Vikram Singh Jul 26 '18 at 07:37
  • first of all, find out what is causing the freezing. if it has something to do with the calculations, then you should use AsyncTask to do the calculations and then do all the UI changes at onPostExecute() method. On the other hand, if the cause of the freezing is the UI changes (adding to much views might be the problem) consider using RecyclerView. – Zacharias Hadjikyprianou Jul 26 '18 at 07:57
  • Yes I think the freeze is coming from the UI loading, will check the RecyclerView, thanks ! – Reaperino Jul 26 '18 at 08:08

3 Answers3

0

I read something about using AsyncTask but I know that AsyncTask is doing computing in a background thread and that you can't update UI through background thread

No, you can update UI, yet not from doInBackground() code. You can either update your UI after heavy lifting is done from onPostExecute() or if you want to update during background computation, delegate that work to onProgressUpdate() method of AsyncTask which runs on UI thread. Then call that method it from doInBackground() when needed.

Marcin Orlowski
  • 72,056
  • 11
  • 123
  • 141
0

When you are in non-UI thread, you can't touch to UI elements directly, but there are multiple workarounds. See, for example, this question.

If you are using AsyncTask, the best way is to override onPostExecute() method of AsyncTask. This method is executed in UI thread (while run() in background thread).

Evgeny Nozdrev
  • 1,530
  • 12
  • 15
0

Check the documentation please, there is an an example too:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Your method addModifLinesToView should be called from doInBackground. All you need is to add the publishProgress calls, on that method you can show to the user which file are you processing.

matheszabi
  • 594
  • 5
  • 16