【发布时间】:2017-06-15 00:10:37
【问题描述】:
我知道关于如何在服务和活动之间进行通信的问题已经回答了很多次,但我也希望我自己的方式得到审查,并知道它是否可以接受并且是正确的方式,并且我如何处理它的缺点是什么。首先,我将尽可能详细地说明问题陈述。
我必须构建一个应用,在其中使用 Firebase 消息服务在两台设备之间进行通信。假设它是一个类似优步的系统。一个应用程序用于服务提供商(司机),一个应用程序用于客户(乘客)。当乘客请求与他们的位置一起旅行时,一定半径内的司机将使用 Firebase 收到带有有效负载的推送通知。 Firebase 服务在后台运行。当服务收到推送通知时,会调用onMessageReceived 方法。生成一个事件。我不是在这里使用 Firebase 来生成通知,而是在我需要使用 Firebase 推送通知的 data 字段时在设备之间实际传输数据。现在,驱动程序应用程序将在 Firebase 推送通知的有效负载中接收用户想要汽车的位置的坐标。我可以简单地使用 extras 中的这些数据启动一个活动,并向驱动程序显示收到了一个请求。
现在在客户方面,在客户提交请求后,他们将被带到下一个活动,在那里他们会看到一个加载屏幕,告诉他们等待一位司机接受他们的请求。当其中一个驱动程序接受此用户的请求时,此用户现在将收到 Firebase 推送通知,该通知的有效负载中包含指定驱动程序的信息。同样,目的不是生成任何通知,而是在设备之间传输数据。
现在您已经了解了用例,我将继续讨论这个问题。
当用户提交请求并移动到下一个等待屏幕时,就会出现问题,在该屏幕上会显示一个加载屏幕,告诉他们在请求等待被其中一位驱动程序接受时等待。当驱动程序接受请求时,正如我所说,用户将收到 Firebase 推送通知,其中驱动程序的信息包含在推送通知的有效负载中。如何在服务和 Activity 之间进行通信,告诉 Activity 停止显示加载屏幕并使用推送通知的有效负载中收到的数据填充 TextView。
这是我的处理方式。假设我有一个名为AwaitingDriver 的活动,其中包含要由驱动程序数据填充的TextView。但目前该活动正在显示加载屏幕,因为该请求尚未被接受。现在,用户在后台运行的服务中收到带有驾驶员信息的推送通知,未以任何方式连接到活动。这是我的onMessageReceived 方法
@Override
public void onMessageReceived(RemoteMessage remoteMessage){
SharedPreferences rideInfoPref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE);
SharedPreferences.Editor rideInfoPrefEditor = rideInfoPref.edit();
String msgType = remoteMessage.getData().get("MessageType");
if (msgType.equals("RequestAccepted")){
rideInfoPrefEditor.putBoolean(getString(R.string.is_request_accepted), true);
rideInfoPrefEditor.putString(getString(R.string.driver_phone), remoteMessage.getData().get("DriverPhone"));
rideInfoPrefEditor.putString(getString(R.string.driver_lat), remoteMessage.getData().get("DriverLatitude"));
rideInfoPrefEditor.putString(getString(R.string.driver_lng), remoteMessage.getData().get("DriverLongitude"));
rideInfoPrefEditor.commit();
AwaitingDriver.requestAccepted(); // A static method in AwaitingDriver Activity
}
}
这里,AwaitingDriver.requestAccepted() 是AwaitingDriver 活动的静态方法。在 AwaitingDriver 活动本身内部,它显示了一个进度对话框来告诉客户等待,这就是 AwaitingDriver.requestAccepted() 方法正在做的事情。
public static void requestAccepted(){
try{
awaitingDriverRequesting.dismiss(); //ProgressDialog for telling user to wait
}catch (Exception e){
e.printStackTrace();
}
if (staticActivity != null){
staticActivity.new TaskFindSetValues().execute();
}
}
这里的staticActivity 是在该类中声明的AwaitingDriver 活动类的静态对象。我在onResume 和onPause 方法中设置它的值。这意味着如果活动在前面,显示在屏幕上,那么staticActivity 的值才会不是null。这是onResume 和onPause 方法。
@Override
public void onResume(){
super.onResume();
staticActivity = this;
Boolean accepted = rideInfoPref.getBoolean(getString(R.string.is_request_accepted), false);
if (accepted){
new TaskFindSetValues().execute();
}
}
@Override
protected void onPause(){
super.onPause();
staticActivity = null;
}
这里,TaskFindSetValues 是在 AwaitingDriver 活动类中定义的 AsyncTask。这是TaskFindSetValues的代码
public class TaskFindSetValues extends AsyncTask<String, Void, String>{
String phone;
String lat;
String lng;
@Override
protected void onPreExecute(){
SharedPreferences pref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE);
phone = pref.getString(getString(R.string.driver_phone), "");
lat = pref.getString(getString(R.string.driver_lat), "");
lng = pref.getString(getString(R.string.driver_lng), "");
}
@Override
protected String doInBackground(String... arg0){
return null;
}
@Override
protected void onPostExecute(String returnValue){
awaitingDriverPhone.setText(phone); //setting values to the TextViews
awaitingDriverLat.setText(lat);
awaitingDriverLng.setText(lng);
}
}
请查看此代码并告诉我这样做而不是其他解决方案的缺点,如果您还可以用相同的示例解释建议的方式,我将非常感激。
【问题讨论】:
-
检查EventBus。这是一种更好、更简单的方法。
标签: android firebase android-asynctask static-methods android-service-binding