在不冻结应用程序的情况下更新UI线程

时间:2018-07-26 07:33:54

标签: android android-asynctask ui-thread

我的代码有问题,我真的是Android世界的新手,我需要AsyncTask类的帮助...

我有一种方法可以搜索CSV文件中的行,然后考虑到确实找到了多少行,这要归功于Map指示要添加哪些视图以及以什么顺序添加它们,从而应该向TableLayout添加特定行。 / p>

该方法可以按我希望的方式工作,但是问题是由于计算冻结了我的应用程序,因此我想做一些事情来向用户指示正在发生的事情。

我读过一些有关使用AsyncTask的知识,但我知道AsyncTask在后台线程中进行计算,并且您无法通过后台线程更新UI

希望您能理解我(我是法语,所以我的英语是近似^^)

这是我的代码:

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();
    }
}

3 个答案:

答案 0 :(得分:0)

  

我读过一些有关使用AsyncTask的知识,但我知道AsyncTask在后台线程中进行计算,并且您无法通过后台线程更新UI

否,您可以更新UI,但不能从doInBackground()代码更新。您可以从onPostExecute()完成繁重的工作后更新UI,或者如果要在后台计算期间进行更新,则可以将工作委托给在UI线程上运行的AsyncTask的onProgressUpdate()方法。然后在需要时从doInBackground()调用该方法。

答案 1 :(得分:0)

在非UI线程中时,无法直接触摸UI元素,但是有多种解决方法。例如,请参见this question

如果您使用的是AsyncTask,则最好的方法是覆盖onPostExecute()的{​​{1}}方法。此方法在UI线程中执行(而AsyncTask在后​​台线程中执行)。

答案 2 :(得分:0)

请检查documentation,也有一个示例:

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");
     }
 }

应该从addModifLinesToView调用您的方法doInBackground。 您只需要添加publishProgress调用,就可以通过该方法向用户显示您正在处理哪个文件。