我在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吗?
答案 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();
}
}
}