Запись в TextView в студии android с использованием AsyncTask [duplicate]

Проблема с «контекстом»

Термин «контекст» иногда используется для ссылки на объект, на который ссылается this . Его использование неуместно, потому что оно не подходит ни семантически, ни технически с помощью ECMAScript в этом .

«Контекст» означает обстоятельства, окружающие что-то, что добавляет смысл , или некоторая предшествующая и следующая информация, которая дает дополнительный смысл. Термин «контекст» используется в ECMAScript для ссылки на контекст выполнения , который является всеми параметрами, областью действия и этой в рамках некоторого исполняемого кода.

Это показано в разделе 10.4.2 ECMA-262 :

Установите значение ThisBinding на то же значение, что и ThisBinding для контекста выполнения вызова

, в котором четко указано, что этот является частью контекста выполнения.

Контекст выполнения предоставляет информацию, которая добавляет смысл в код, который выполняется , Он содержит гораздо больше информации о том, что только thisBinding .

Таким образом, значение этого не является «контекстом», это всего лишь одна часть выполнения контекст. Это, по сути, локальная переменная, которая может быть задана вызовом любого объекта и в строгом режиме для любого значения вообще.

591
задан Igor Tyulkanov 14 December 2015 в 03:26
поделиться

13 ответов

Хорошо, вы пытаетесь получить доступ к графическому интерфейсу через другой поток. Это, в основном, не является хорошей практикой.

AsyncTask выполняет все в doInBackground() внутри другого потока, который не имеет доступа к графическому интерфейсу, где ваши представления.

preExecute() и postExecute() предлагают вам доступ к графическому интерфейсу до и после тяжелого подъема в этом новом потоке, вы можете даже передать результат длинной операции postExecute(), чтобы затем показать какие-либо результаты обработки.

См. эти строки, где вы позже обновив TextView:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

поместите их в PostExecute()

После этого вы увидите текст TextView после завершения doInBackground.

EDIT : Я заметил, что ваш слушатель onClick не проверяет, какой вид был выбран. Я считаю, что самый простой способ сделать это - с помощью операторов switch. [Править]

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

    Button btn;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) findViewById(R.id.button1);
        // because we implement OnClickListener we only have to pass "this"
        // (much easier)
        btn.setOnClickListener(this);
    }

    public void onClick(View view) {
        // detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            new LongOperation().execute("");
            break;
        }
    }

    private class LongOperation extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... params) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed"); // txt.setText(result);
            // might want to change "executed" for the returned string passed
            // into onPostExecute() but that is upto you
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}
616
ответ дан Graham Smith 20 August 2018 в 22:02
поделиться
  • 1
    Я не могу это сделать & lt; code & gt; btn.setOnClickListener (это); & Lt; / код & GT; Eclipse дает ошибку ----- & quot; Метод setOnClickListener (View.OnClickListener) в типе View не применим для аргументов (AsyncTaskActivity) & quot; – Fox 12 March 2012 в 19:33
  • 2
    Я бы посоветовал изменить настройку текста, чтобы он не был статичным, но принять аргумент из метода onPostExecute(String result). Для будущих читателей было бы более ясно, что аргумент заполняется возвращаемым значением doInBackground(String... params). – Eric 28 December 2012 в 12:37
  • 3
    @ Эрик Тобиас - Точные вещи, сделанные в комментариях. Я отвечал и отвечал на вопрос пользователей в моем полном примере. – Graham Smith 30 December 2012 в 23:13
  • 4
    @Graham Действительно, я видел комментарий. Однако я считаю, что лучше вообще не ссылаться на статическое назначение. Это, на мой взгляд, плохая привычка, и ее следует избегать. Не говоря уже о том, что такой замечательный ответ, как и ваш, обязан преподавать и хорошие практики! ;) – Eric 2 January 2013 в 15:46
  • 5
    В качестве дополнения и селектора Google (и, возможно, от кого-то, кто в настоящее время изучает этот материал, каким образом я сталкивался с этим): большинство обновлений пользовательского интерфейса вы сделаете для чего-то, в котором вам нужен прогресс, о котором сообщается обратно пользователю, в обратном вызове onProgressUpdate который выполняется в основном потоке пользовательского интерфейса. – RichieHH 21 January 2014 в 22:45

Концепция и код здесь

Я создал простой пример использования AsyncTask для Android. Он начинается с onPreExecute(), doInBackground(), publishProgress() и, наконец, onProgressUpdate().

В этом doInBackground () работает как фоновый поток, а другой работает в потоке пользовательского интерфейса. Вы не можете получить доступ к элементу пользовательского интерфейса в doInBackground (). Последовательность такая же, как я упомянул.

Однако, если вам нужно обновить какой-либо виджет из doInBackground, вы можете publishProgress из doInBackground, который будет вызывать onProgressUpdate, чтобы обновить виджет пользовательского интерфейса.

class TestAsync extends AsyncTask<Void, Integer, String>
{
    String TAG = getClass().getSimpleName();

    protected void onPreExecute (){
        super.onPreExecute();
        Log.d(TAG + " PreExceute","On pre Exceute......");
    }

    protected String doInBackground(Void...arg0) {
        Log.d(TAG + " DoINBackGround","On doInBackground...");

        for(int i=0; i<10; i++){
            Integer in = new Integer(i);
            publishProgress(i);
        }
        return "You are at PostExecute";
    }

    protected void onProgressUpdate(Integer...a){
        super.onProgressUpdate(a);
        Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.d(TAG + " onPostExecute", "" + result);
    }
}

Вызвать это в своей деятельности следующим образом:

new TestAsync().execute();

Справочник разработчика Здесь

49
ответ дан byteC0de 20 August 2018 в 22:02
поделиться
  • 1
    классы начинаются с обычно заглавных букв на Java, это обычная запись – Vamsi Pavan Mahesh 13 March 2014 в 17:35

Я уверен, что он выполняется правильно, но вы пытаетесь изменить элементы пользовательского интерфейса в фоновом потоке, и это не будет сделано.

Пересмотрите свой вызов и AsyncTask следующим образом:

Класс вызова

Примечание. Я лично предлагаю использовать onPostExecute() везде, где вы выполняете поток AsyncTask, а не в классе, который расширяет сам AsyncTask. Я думаю, что это упрощает чтение кода, особенно если вам нужна AsyncTask в нескольких местах, обрабатывающих результаты, несколько отличающиеся.

new LongThread()
{
    @Override public void onPostExecute(String result)
    {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}.execute("");

Класс LongThread (расширяет AsyncTask):

@Override
protected String doInBackground(String... params) {
    for(int i = 0; i < 5; i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    return "Executed";
}      
643
ответ дан Community 20 August 2018 в 22:02
поделиться
  • 1
    Спасибо за предоставление примера, который отделяет AsyncTask от Activity – sthomps 7 August 2014 в 20:11
  • 2
    лучшее и быстрое объяснение 3-х параметров AsyncTask .... + 1 для вас – Zaffar Saffee 22 May 2015 в 20:36
  • 3
    params - массив. (В приведенном выше примере это был массив String.) Это позволяет вам передавать несколько параметров одного и того же типа. Затем вы можете получить доступ к этим параметрам с помощью params[0], params[1], params[2] и т. Д. В примере в массиве params был только один String. Если вам нужно передать несколько параметров разных типов (например, String и int), см. этот вопрос . – Suragch 2 February 2016 в 02:29
  • 4
    да, наконец, кто-то отделяет задачу и деятельность. спасибо. И переопределение onPostExecute в деятельности блестяще. – mcy 25 May 2017 в 08:56

Вам нужно объявить кнопку onclicklistener, как только щелкнуть по ней, вызывает класс AsyncTask DownloadJson, процесс будет показан ниже:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
             new DownloadJson().execute();
            }
        });

    }

     // DownloadJSON AsyncTask
    private class DownloadJson extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected  Void doInBackground(Void... params) {
            newlist = new ArrayList<HashMap<String, String>>();
             json = jsonParser.makeHttpRequest(json, "POST");
            try {
                newarray = new JSONArray(json);
                    for (int i = 0; i < countdisplay; i++) {
                        HashMap<String, String> eachnew = new HashMap<String, String>();
                        newobject = newarray.getJSONObject(i);
                        eachnew.put("id", newobject.getString("ID"));
                        eachnew.put("name", newobject.getString("Name"));
                        newlist.add(eachnew);
                    }
                }
            } catch (JSONException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void args) {
            newlisttemp.addAll(newlist);
            NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp);
            newpager.setAdapter(newadapterpager);
        }
    }
1
ответ дан Cristiana Chavez 20 August 2018 в 22:02
поделиться

Когда выполняется асинхронная задача, задача выполняет 4 этапа:

  1. onPreExecute ()
  2. doInBackground (Params ...)
  3. onProgressUpdate (Прогресс ...)
  4. onPostExecute (Результат)

Ниже приведен демонстрационный пример

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

, и как только вы создали, задача выполняется очень просто:

 new DownloadFilesTask().execute(url1, url2, url3);

Надеюсь, это поможет вам ...

9
ответ дан Ganesh Katikar 20 August 2018 в 22:02
поделиться
  • 1
    execute ожидает параметр Runnable. Он не принимает строку. Каков тип вашего URL-адреса? строка или нет – user 13 July 2017 в 11:23

Я бы рекомендовал облегчить вашу жизнь, используя эту библиотеку для фоновых работ https://github.com/Arasthel/AsyncJobLibrary

. Это просто ..

AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {

    @Override
    public void doOnBackground() {
        startRecording();
    }
});
4
ответ дан kc ochibili 20 August 2018 в 22:02
поделиться

Измените свой код следующим образом:

@Override
protected void onPostExecute(String result) {

    runOnUiThread(new Runnable() {
        public void run() {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
        }
    });
}
6
ответ дан Peter Mortensen 20 August 2018 в 22:02
поделиться
  • 1
    Вам не нужно использовать runOnUiThread, поскольку onPostExecute всегда работает в потоке 1 (не так ли?) – justdan0227 16 July 2016 в 16:49

Переместите эти две строки:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

из вашего метода doInBackground AsyncTask и поместите их в метод onPostExecute. Ваш AsyncTask должен выглядеть примерно так:

private class LongOperation extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(5000); // no need for a loop
        } catch (InterruptedException e) {
            Log.e("LongOperation", "Interrupted", e);
            return "Interrupted";
        }
        return "Executed";
    }      

    @Override
    protected void onPostExecute(String result) {               
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}
15
ответ дан Ted Hopp 20 August 2018 в 22:02
поделиться
  • 1
    Эй, что я запускаю async-задачу на службе, я хочу вернуть некоторое значение в основной поток ui. – Dipen 21 January 2015 в 17:31
  • 2
    @Dipen - Проверьте это обсуждение . Существует два вопроса: вывод результатов из AsyncTask, на которые я отвечаю; и отправляет значение из службы в поток ui, к которому обращается другая дискуссия. Эти вопросы независимы. – Ted Hopp 21 January 2015 в 21:25

Справочная информация / Теория

AsyncTask позволяет запускать задачу в фоновом потоке при публикации результатов в потоке пользовательского интерфейса.

Пользователь всегда должен взаимодействовать с приложением, поэтому важно не блокировать основной поток (UI) такими задачами, как загрузка содержимого из Интернета.

Вот почему мы используем AsyncTask.

Он предлагает простой интерфейс , обертывающий очередь сообщений и обработчик потока пользовательского интерфейса, которые позволяют отправлять и обрабатывать запущенные объекты и сообщения из других потоков .

Реализация

AsyncTask - это общий класс. (Он принимает параметризованные типы в своем конструкторе.)

Он использует эти три общих типа:

Params - тип параметров, отправленных в задачу после выполнения.

Progress - тип единиц прогресса, опубликованных во время фонового вычисления.

Result - тип результата фонового вычисления.

] Не все типы всегда используются асинхронной задачей. Чтобы пометить тип как неиспользованный, просто используйте тип Void:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

Эти три параметра соответствуют трем основным функциям, которые вы можете переопределить в AsyncTask:

  • doInBackground(Params...)
  • onProgressUpdate(Progress...)
  • onPostExecute(Result)

Для выполнения AsyncTask

вызывать execute() с параметрами, которые будут отправлены в фоновое задание.

Что происходит

  1. В главном / пользовательском потоке вызывается onPreExecute(). (Чтобы инициализировать что-то в этом потоке, например, показать индикатор выполнения в пользовательском интерфейсе.)
  2. В фоновом потоке вызывается doInBackground(Params...). (Параметры - это те, которые передаются функции Execute.) В тех случаях, когда должно выполняться многолетняя задача. Чтобы использовать AsyncTask, необходимо переопределить хотя бы doInBackground(). Вызовите publishProgress(Progress...), чтобы обновить отображение прогресса в пользовательском интерфейсе, пока выполняется фоновое вычисление. (например, анимировать индикатор выполнения или показывать журналы в текстовом поле.) Это вызывает вызов onProgressUpdate().
  3. В фоновом потоке результат возвращается из doInBackground(). Это приводит к следующему шагу.
  4. В главном / пользовательском потоке, onPostExecute() вызывается с возвращенным результатом.

Примеры

Используя снова Например, задача блокировки заключается в загрузке чего-либо из Интернета,

  • Пример A загружает изображение и отображает его в ImageView,
  • , в то время как в примере B загружаются некоторые файлы.

Пример A

Метод doInBackground() загружает изображение и сохраняет его в объекте типа BitMap. Метод onPostExecute() принимает растровое изображение и помещает его в ImageView.

class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bitImage;

    public DownloadImageTask(ImageView bitImage) {
        this.bitImage = bitImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mBmp = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mBmp = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mBmp;
    }

    protected void onPostExecute(Bitmap result) {
        bitImage.setImageBitmap(result);
    }
}

Пример B

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

Пример выполнения B

new DownloadFilesTask().execute(url1, url2, url3);
7
ответ дан TT-- 20 August 2018 в 22:02
поделиться
 private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(false);
        progressDialog.show();

    }

    @Override
    protected Void doInBackground(Void... arg0) {

        //do code here 

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }

    }

    @Override
    protected void onCancelled() {

        super.onCancelled();
        progressDialog.dismiss();
        Toast toast = Toast.makeText(getActivity(),
                "Error is occured due to some probelm", Toast.LENGTH_LONG);
        toast.setGravity(Gravity.TOP, 25, 400);
        toast.show();

    }

}
1
ответ дан Vaishali Sutariya 20 August 2018 в 22:02
поделиться

Самый короткий пример для асинхронного выполнения:

class MyAsyncTask extends android.os.AsyncTask {
    @Override
    protected Object doInBackground(Object[] objects) {
        //do something asynchronously
        return null;
    }
}

Чтобы запустить его:

(new MyAsyncTask()).execute();
10
ответ дан WhereDatApp.com 20 August 2018 в 22:02
поделиться
668
ответ дан Community 31 October 2018 в 17:03
поделиться
6
ответ дан Peter Mortensen 31 October 2018 в 17:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: