Можно ли заставить блок setOnClickListener ожидать вызова метода внутри него? - PullRequest
1 голос
/ 22 апреля 2019

Сначала у меня есть вызов метода внутри блока setOnClickListener, который получает какое-то значение от API, который я использую для запуска живого потока, важно, чтобы этот вызов метода завершился, прежде чем что-либо еще будет сделано внутри блока в чтобы получить правильный результат, потому что все остальное после этого вызова метода первой строки зависит от этого.

Фрагмент кода:

myButton.setOnClickListener {

            // Everything depends on check stream call
            currentViewModel.checkStream()

            if (!PlaybackService.isServiceStarted) {
                if (isStreaming!!) {
                    onPlayerStart()
                    sliding_player.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
                } else
                    Snackbar.make(appbar, R.string.stream_fail, Snackbar.LENGTH_LONG).show()
            }
        }

Мне нужно, чтобы блок myButton.setOnClickListener ожидал
currentViewModel.checkStream() для правильной работы следующих строк (дать правильный результат).

Возможно ли это сделать? Используя какой-то метод обратного вызова? Должен ли я сделать это с Retrofit2?

Ответы [ 4 ]

1 голос
/ 22 апреля 2019

Вы никогда не должны ждать в главном потоке, а onClick() вызывается в главном потоке.

Вы можете рассмотреть асинхронную среду для обработки вашего варианта использования. Эти структуры будут включать RxJava , AsyncTask или даже простые Handler реализации. Чтобы быть ближе к вашей реальной реализации, Kotlin Coroutines может быть наиболее подходящим, так как переключение обратно в основной поток очень ясно. Он также хорошо интегрируется с Retrofit .

myButton.setOnClickListener {
    coroutineScope.launch(Dispatchers.IO) {
        // make sure checkStream() is a suspending function
        // to wait for it execution to finish
        currentViewModel.checkStream()

        if (!PlaybackService.isServiceStarted) {
            launch(Dispatchers.Main) {
                if (isStreaming!!) {
                    onPlayerStart()
                    sliding_player.panelState = COLLAPSED
                } else {
                    Snackbar.make(appbar, R.string.stream_fail, LENGTH_LONG).show()
                }
            }
        }
    }
}

coroutineScope, который необходимо подключить к жизненному циклу, чтобы не пропустить действие или фрагмент.

0 голосов
/ 22 апреля 2019

сделать ваш сетевой вызов внутри класса Asycn и используйте как указано ниже код

myButton.setOnClickListener {
    //start asycn call from here
    // new Async().execute();
        }

class Async extends Async{
    onPreExecute(){}

    doInBackground(){
        // below method call should be synchronised
        currentViewModel.checkStream()
    }

    onPostExecute(){
        if (!PlaybackService.isServiceStarted) {
                if (isStreaming!!) {
                    onPlayerStart()
                    sliding_player.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
                } else
                    Snackbar.make(appbar, R.string.stream_fail, Snackbar.LENGTH_LONG).show()
            }
    }

}
0 голосов
/ 22 апреля 2019

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

Проверьте ниже вызов AsyncTask.

public class AsyncUploadStream extends AsyncTask<String, Integer, Object> {

    private ProgressDialog dialog;

    public AsyncUploadStream() {   
        dialog = new ProgressDialog(context);
        dialog.setMessage("Please Wait...");
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dialog.show();
    }

    @Override
    public Object doInBackground(String... params) {
        return currentViewModel.checkStream();
    }

    @Override
    public void onPostExecute(Object result) {
        super.onPostExecute(result);

        if (dialog != null && dialog.isShowing())
            dialog.dismiss();

        try {

            if (!PlaybackService.isServiceStarted) {
                if (isStreaming !!){
                    onPlayerStart()
                    sliding_player.panelState = SlidingUpPanelLayout.PanelState.COLLAPSED
                } else{
                    Snackbar.make(appbar, R.string.stream_fail, Snackbar.LENGTH_LONG).show()
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
0 голосов
/ 22 апреля 2019

Попробуйте сначала вызвать API, а затем получить ответ для вызова вашего метода следующим образом.

Call<UploadObject> fileUpload = uploadImage.uploadFile(fileToUpload, filename);
        fileUpload.enqueue(new Callback<UploadObject>() {
            @Override
            public void onResponse(Call<UploadObject> call, Response<UploadObject> response) {
                Toast.makeText(MainActivity1.this, "Success " + response.message(), Toast.LENGTH_LONG).show();
                Toast.makeText(MainActivity1.this, "Success " + response.body().toString(), Toast.LENGTH_LONG).show();
            }

            @Override
            public void onFailure(Call<UploadObject> call, Throwable t) {
                Log.d(TAG, "Error " + t.getMessage());
            }
        });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...