2016-06-19 4 views
2

У меня есть MainActivity, SecondaryActivity и класс AsyncTask.
MainActivity имеет метод, называемый doSomething()Позвоните по другому методу деятельности от AsyncTask

я называю AsyncTask из MainActivity так:

new asyncTask(MainActivity.this).execute(); 

Что означает, что я могу сослаться на MainActivity в моем onPostExecute

@Override 
protected void onPostExecute(Boolean result){ 
    super.onPostExecute(result); 
    # activity is defined as this.activity 
    activity.doSomething();  
} 

Как я могу назвать AsyncTask из моей SecondaryActivity аналогичным образом, потому что мне нужна ссылка на мою MainActivity для доступа к его методам?

EDIT: Я бы хотел, чтобы doSomething() вызывался в любое время. Так что даже если это из SecondActivity, после завершения его фоновой операции -> doSomething()

Метод, который я вызываю, обновляет экран MainActivity для отображения изменений данных. Вторичная активность вызывает только AsyncTask, когда она приостанавливается/останавливается/уничтожается, но в настоящее время Asynctask заканчивается после запуска MainActivity и поэтому изменения не отображаются.

+0

Трудно понять ваш вопрос. Мое предположение: у вас есть класс MainActivity, SecondaryActivity и UpsertTask, который расширяет AsyncTask. Теперь вы хотите использовать UpsertTask в обоих действиях, но вызывать разные методы в зависимости от класса вызывающего. Я прав?? – Tony

+0

@Tony Это точно правильно – Lobstw

ответ

0

Один из способов сделать это можно с помощью шины событий. Это способ передачи сообщений/данных между действиями. Вы можете отправлять сообщения на автобус, а затем действия могут прослушивать сообщение, если они регистрируются.

EventBus класс (индивидуальный)

public class EventBus extends Bus { 
    private static final EventBus bus = new EventBus(); 
    public static Bus getInstance() { return bus; }  
    private EventBus() {} 
} 

MainActivity класс

... 
@Override 
protected void onResume() { 
    super.onResume(); 
    EventBus.getInstance().register(this); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    EventBus.getInstance().unregister(this); 
} 

@Subscribe 
public void asyncDone(String message) { 
    foo(message)  
} 

AsyncTask класс

... 
@Override 
protected void onPostExecute(Boolean result){ 
    super.onPostExecute(result); 
    EventBus.getInstance().post("My data") 

Благодаря @theheartbreakpug от Reddit за предоставление мне этого решения.

2

Я думаю, что ваша AsyncTask вложенна в MainActivity в настоящее время. Лучше вы поместите его в отдельный класс. Какой бы параметр ни требовал от него, передайте его в своем конструкторе. Пусть обе ваша деятельность реализует один и тот же интерфейс. Что-то вроде этого

class MainActivity/SecondaryActivity implements DoSomethingListener { 
    void doSomething() { 
    } 
} 

Также передайте ссылку своей деятельности AsyncTask в конструкторе.

И наконец, onPostExecute, поскольку у вас есть ссылка на MainActivity или Secondary Activity. Вызов activity.doЧто-то.

+0

Это отдельный класс, а не вложенный – Lobstw

+0

, тогда вам просто нужно реализовать общий интерфейс как в действиях, так и вызвать метод интерфейса onPostExecute() –

+0

Это прекрасное решение, мне оно нравится. – Vucko

0

Попробуйте это в своем классе UpsertTask.

private Context mContext; 

public UpsertTask(Context context){ 
    mContext = context; 
} 

@Override 
protected void onPostExecute(Object o) { 
    super.onPostExecute(o); 

    if(mContext instanceof MainActivity){ 
     ((MainActivity) mContext).doSomething(); 
    } 
    else if(mContext instanceof SecondActivity){ 
     ((SecondActivity) mContext).doSomethingElse(); 
    } 
} 
+0

Спасибо за ответ. Мой желаемый результат - всегда иметь onPostExecute вызов 'doSomething()'. Нуль, который я получил в этом примере, был всего лишь частью теста. Поэтому, если это SecondActivity, мне нужно будет получить MainActivity в какой-то момент – Lobstw

+0

@Lobstw, который звучит как действительно очень плохой дизайн. Вы должны пересмотреть это. –

+0

@TodorKostov Метод, который я вызываю, обновляет экран mainactivity, чтобы показать изменения данных. Вторичная активность вызывает только AsyncTask, когда она приостанавливается/останавливается/уничтожается, но в настоящее время асинхронизация заканчивается после запуска MainActivity и поэтому изменения не отображаются. – Lobstw

0
@Override 
protected void onPostExecute(Boolean result){ 
    super.onPostExecute(result); 
    # activity is defined as this.activity 
    if (activity != null) { 
     if(activity instanceof MainActivity) { 
     activity.doSomething(); 
     } else if(activity instanceof SecondaryActivity) { 
     activity.doSomethingElse(); 
     } 
    } 
} 

Я думаю, что будет работать. (если вы правильно поняли ваш вопрос).

+0

Я отредактировал свой вопрос, извините за путаницу – Lobstw

2

Я думаю, вы хотите что-то обновить в MainActivity на основе результата AsyncTask, вызванного от SecondaryActivity. В этом случае я предлагаю позвонить SecondaryActivity с startActivityForResult. Затем в вашем onPostExecute вызовите setResult, чтобы установить флаг или некоторые данные.

И наконец, в MainActivity переопределить onActivityResult для вызова doSomething, когда код запроса соответствует SecondaryActivity.

+0

Ваш ответ кажется наиболее перспективным до сих пор. Тем не менее, я не могу 'setResult', потому что активность равна нулю к моменту, когда она находится onPostExecute. – Lobstw

+0

Я немного поспешил назвать это решение, извините за это. Если я делаю setResult на onPostExecute, то код результата не будет правильно вставлен/установлен, и моя mainactivity не сможет увидеть код. – Lobstw

+0

Я предположил, что вы делаете activity.setResult в onPostExecute, где action является экземпляром SecondaryActivity. Позже, когда пользователь возвращается к MainActivity, выполняется doSomething. – jaibatrik

1

Итак, ваше требование состоит в том, чтобы иметь единственный экземпляр MainActivity. Данные в MainActivity могут обновляться из MainActivity или SecondaryActivity. В любом случае данные, подлежащие обновлению, получают с использованием AsyncTask.

Мой Предложение

Добавьте следующий к MainActivity в манифесте, (Подробнее о android:launchMode здесь.)

android:launchMode="singleInstance" 

Когда вы закончили взаимодействие с SecondaryActivity, сделать это,

Intent intent = new Intent(this, MainActivity.class); 
    intent.putExtra("DATA1", "your_data1"); 
    intent.putExtra("DATA2", "your_data2"); 
    startActivity(intent); 
    finish(); 

Затем в MainActivity,

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 

    String data1 = intent.getStringExtra("DATA1"); 
    String data2 = intent.getStringExtra("DATA2"); 
} 

Затем вызовите AsyncTask в MainActivity с помощью data1 и data2.

ПРИМЕЧАНИЕ. Это один из способов приблизиться к вашей проблеме. Существуют другие подходы, такие как startActivityForResult() в зависимости от ваших требований.

UPDATE Если вы хотите отменить AsyncTask, звоните asyncTask.cancel(true); Однако, это не будет гарантировать ваш HttpRequest прерывается, так как отмена вступит в силу после того, как запрос завершен. Обход для этого немного хакерский. После вызова функции cancel(), убедитесь, что isCancelled() истинно, тогда сделайте httpRequest.abort() Это будет только самый быстрый способ завершить задачу async. Не обязательно означает, что запрос прерывается.

+0

Спасибо, что присоединились ко мне. Это очень хорошее решение. Есть ли что-нибудь, что я могу сделать, чтобы избежать потенциальной потери данных (если пользователь закрывает приложение - так что намерение никогда не запускалось, или если пользователь переходит к различной активности)? – Lobstw

+0

@Lobstw, см. Мое ОБНОВЛЕНИЕ выше. Между тем, если вы найдете мой ответ удовлетворительным, пожалуйста, примите. – Tony

+0

Я решил проблему с использованием шины событий, см. Решение и, пожалуйста, предложите улучшения, если у вас есть – Lobstw

Смежные вопросы