Андроидная андроидальная передача, отправляющая обратные вызовы в ui
У меня есть следующий класс asynctask, который не находится внутри операции. В этой операции я инициализирую асинтезу, и я хочу, чтобы асинтекс сообщал обратные вызовы к моей активности.
Является ли это возможным? Или асинхронность должна быть в том же файле класса, что и активность?
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
caller.sometextfield.setText("bla");
}
Что-то вроде этого?
Ответы
Ответ 1
Вы можете создать interface
, передать его AsyncTask
(в конструкторе), а затем вызвать метод в onPostExecute()
Например:
Ваш интерфейс:
public interface OnTaskCompleted{
void onTaskCompleted();
}
Ваша деятельность:
public class YourActivity implements OnTaskCompleted{
// your Activity
}
И ваш AsyncTask:
public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
private OnTaskCompleted listener;
public YourTask(OnTaskCompleted listener){
this.listener=listener;
}
// required methods
protected void onPostExecute(Object o){
// your stuff
listener.onTaskCompleted();
}
}
ИЗМЕНИТЬ
Поскольку этот ответ получил довольно популярный, я хочу добавить некоторые вещи.
Если вы новичок в разработке Android, AsyncTask
- это быстрый способ заставить все работать, не блокируя поток пользовательского интерфейса. Это действительно решает некоторые проблемы, нет ничего плохого в том, как класс работает сам. Однако это приводит к некоторым последствиям, например:
- Возможность утечки памяти. Если вы сохраните ссылку на свой
Activity
, он останется в памяти даже после того, как пользователь покинет экран (или повернет устройство).
-
AsyncTask
не доставляет результат до Activity
, если Activity
уже был уничтожен. Вы должны добавить дополнительный код, чтобы управлять всем этим или выполнять операции дважды.
- Сопряженный код, который делает все в
Activity
Когда вы чувствуете, что достаточно созрели для перехода на Android, посмотрите эту статью, которая, я думаю, является лучшим способом для разработки ваших приложений Android с асинхронными операциями.
Ответ 2
Я чувствовал, что подход ниже очень прост.
Я объявил интерфейс для обратного вызова
public interface AsyncResponse {
void processFinish(Object output);
}
Затем создана асинхронная задача для ответа на все типы параллельных запросов
public class MyAsyncTask extends AsyncTask<Object, Object, Object> {
public AsyncResponse delegate = null;//Call back interface
public MyAsyncTask(AsyncResponse asyncResponse) {
delegate = asyncResponse;//Assigning call back interfacethrough constructor
}
@Override
protected Object doInBackground(Object... params) {
//My Background tasks are written here
return {resutl Object}
}
@Override
protected void onPostExecute(Object result) {
delegate.processFinish(result);
}
}
Затем вызывается асинхронная задача при нажатии кнопки в классе активности.
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
Button mbtnPress = (Button) findViewById(R.id.btnPress);
mbtnPress.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {
@Override
public void processFinish(Object output) {
Log.d("Response From Asynchronous task:", (String) output);
mbtnPress.setText((String) output);
}
});
asyncTask.execute(new Object[] { "Youe request to aynchronous task class is giving here.." });
}
});
}
}
Спасибо
Ответ 3
В завершении к приведенным выше ответам вы также можете настроить резервные копии для каждого асинхронного вызова, который вы делаете, чтобы каждый вызов общего метода ASYNC заполнял разные данные, в зависимости от содержимого onTaskDone, которое вы там помещали.
Main.FragmentCallback FC= new Main.FragmentCallback(){
@Override
public void onTaskDone(String results) {
localText.setText(results); //example TextView
}
};
new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id);
Напоминаем: я использовал интерфейс для основного действия, в котором происходит "Main", например:
public interface FragmentCallback {
public void onTaskDone(String results);
}
Выполнение моего API-сообщения выглядит следующим образом:
@Override
protected void onPostExecute(String results) {
Log.i("TASK Result", results);
mFragmentCallback.onTaskDone(results);
}
Конструктор API выглядит следующим образом:
class API_CALL extends AsyncTask<String,Void,String> {
private Main.FragmentCallback mFragmentCallback;
private Context act;
private String method;
public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) {
act=ctx;
method=api_method;
mFragmentCallback = fragmentCallback;
}
Ответ 4
Я повторю то, что говорили другие, но просто попытаюсь сделать это проще...
Сначала просто создайте класс интерфейса
public interface PostTaskListener<K> {
// K is the type of the result object of the async task
void onPostTask(K result);
}
Во-вторых, создайте AsyncTask (который может быть внутренним статическим классом вашей активности или фрагмента), который использует интерфейс, путем включения конкретного класса. В этом примере PostTaskListener параметризуется String, что означает, что он ожидает класс String в результате задачи async.
public static class LoadData extends AsyncTask<Void, Void, String> {
private PostTaskListener<String> postTaskListener;
protected LoadData(PostTaskListener<String> postTaskListener){
this.postTaskListener = postTaskListener;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null && postTaskListener != null)
postTaskListener.onPostTask(result);
}
}
Наконец, часть, где вы комбинируете свою логику. В своей деятельности/фрагменте создайте PostTaskListener и передайте его в async-задачу. Вот пример:
...
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() {
@Override
public void onPostTask(String result) {
//Your post execution task code
}
}
// Create the async task and pass it the post task listener.
new LoadData(postTaskListener);
Готово!