是否可以让setOnClickListener块等待内部的方法调用?

时间:2019-04-22 08:59:11

标签: android kotlin retrofit2

我在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 个答案:

答案 0 :(得分:1)

您永远不要在主线程上等待,并且在主线程上调用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才能泄漏活动或片段。

答案 1 :(得分:0)

尝试先调用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());
            }
        });

答案 2 :(得分:0)

在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()
            }
    }

}

答案 3 :(得分:0)

如果在主线程上调用API是可能的,但是它将卡住UI。因此,最好的方法是以异步方式调用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();
        }
    }
}
相关问题