Подтвердить что ты не робот

Как вернуть результаты IntentService в Activity?

Я использую IntentService для обработки сетевых сообщений с сервером через JSON. Часть JSON/server работает нормально, но мне трудно получить результаты туда, где они нужны. Следующий код показывает, как я запускаю службу намерений изнутри onClick(), а затем обновляю глобальную переменную для ретрансляции результатов обратно в основное действие.

public class GXActivity extends Activity {

    private static final String TAG = "GXActivity";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // === called when the activity is first created

        Log.i(TAG, "GXActivity Created");

        super.onCreate(savedInstanceState);
        setContentView(R.layout.start);

        View.OnClickListener handler = new View.OnClickListener() {
            public void onClick(View v) {

                // === set up an application context to hold a global variable
                // === called user, to contain results from the intent service
                GXApp appState = ((GXApp) getApplicationContext());
                User user = new User(-1); // initialize user id to -1
                appState.setUser(user);

                // === next start an intent service to get JSON from the server;
                // === this service updates the user global variable with
                // === results from the JSON transaction
                Intent intent = new Intent(this, GXIntentService.class);
                startService(intent);

                // === check app context for results from intent service
                appState = ((GXApp) getApplicationContext());
                if (appState.getUser().getId() != -1)...

            }
        }
    }
}

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

Что мне делать по-другому, чтобы служба вызова вызывалась до проверки результатов? Будет ли это работать, если я вытащил бы прослушиватель кликов из функции onCreate()? Есть ли другой/лучше структурировать этот код? Большое спасибо.

4b9b3361

Ответ 1

Вы должны посмотреть на создание своего собственного ResultReceiver подкласса в своей деятельности. ResultReceiver реализует Parcelable, поэтому его можно передать из Activity в Service в качестве дополнительного в Intent.

Вам нужно будет сделать что-то вроде этого:

  • Внедрите подкласс класса ResultReceiver в свой класс активности. Ключевым методом реализации является onReceiveResult(). Этот метод предоставляет вам Bundle данных результата, которые могут использоваться для передачи любой информации, которую вы извлекаете в Service. Просто распакуйте нужные данные и используйте их для обновления своей активности.

  • В своей деятельности создайте новый экземпляр своего пользовательского ResultReceiver и добавьте его в Intent, который вы используете для запуска вашей службы.

  • В вашем методе Service onStartCommand() извлеките ResultReceiver, переданный в Intent, и сохраните его в локальной переменной-члене.

  • Как только ваш Service завершит свою работу, вызовите send() в ResultReceiver, передавая все данные, которые вы хотите отправить обратно в действие в Bundle.

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

Ответ 2

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

1- отправить намерение трансляции (содержащее статус в своих расширенных данных) в конце работы в IntentService

2- реализуйте LocalBroadcastReceiver в вашей деятельности, который потребляет данные из Intent

Это также рекомендуется в официальной документации (если вы хотите использовать свой IntentService):

https://developer.android.com/training/run-background-service/report-status.html

Ответ 3

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

Ответ 4

Вы можете использовать Otto библиотеку. Otto - проект с открытым исходным кодом, предназначенный для реализации реализации шины данных, чтобы компоненты могли публиковать и подписываться на события.