Android Asynctask отправка обратных вызовов для пользовательского интерфейса
У меня есть следующий класс asynctask, который не находится внутри деятельности. В упражнении я инициализирую asynctask и хочу, чтобы asynctask сообщала обратные вызовы моей деятельности. Является ли это возможным? Или асинхронная задача должна быть в том же файле класса, что и действие?
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
caller.sometextfield.setText("bla");
}
Что-то вроде этого?
4 ответа
Вы можете создать 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 с асинхронными операциями.
Я чувствовал, что приведенный ниже подход очень прост.
Я объявил интерфейс для обратного вызова
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.." });
}
});
}
}
Спасибо
В дополнение к ответам, приведенным выше, вы также можете настроить свои запасные варианты для каждого асинхронного вызова, который вы делаете, так что каждый вызов универсального метода 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;
}
Я повторю то, что сказали другие, но постараюсь сделать это проще...
Во-первых, просто создайте класс Interface
public interface PostTaskListener<K> {
// K is the type of the result object of the async task
void onPostTask(K result);
}
Во-вторых, создайте AsyncTask (который может быть внутренним статическим классом вашей деятельности или фрагмента), который использует интерфейс, включив конкретный класс. В этом примере PostTaskListener параметризован с помощью String, что означает, что он ожидает класс String в результате асинхронной задачи.
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 и передайте его асинхронной задаче. Вот пример:
...
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);
Готово!