我正在制作一个使用设备传感器和位置的安卓应用程序。来自这两个来源的数据将用于计算有关方向的一些事情。到目前为止,我创建了两个非活动类,一个用于传感器管理,一个用于位置管理。问题是当我想使用需要活动或上下文来完成的事情时,例如:通过调用startResolutionForResult()
显示对话框,并在onActivityResult()
中检查结果。startResolutionForResult()
需要活动才能显示对话框。 解决这个问题的最佳方法是什么?我决定使用上下文作为每个非活动类的字段成员,但我不确定这是否是最佳选择。
更新这是我引用的代码的一部分。
onCreate()
方法中,我调用checkLocationSettings()
方法来检查位置是否打开。Then onResult()
回调触发,我可以根据位置设置确定要执行的操作。当位置处于关闭状态时,它会显示由 调用的对话框
status.startResolutionForResult((Activity)getBaseContext(), REQUEST_CHECK_SETTINGS)
用户决策的结果可在onActivityResult()
中找到,这是MainActivity的一部分.class 一切都像一个魅力,但我特别关注(Activity)getBaseContext()。
GoogleServiceLocationProvider.class
public class GoogleServiceLocationProvider extends ContextWrapper implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener, ResultCallback<LocationSettingsResult> {
private static final int REQUEST_CHECK_SETTINGS = 3;
private static final int UPDATE_INTERVAL = 10 * 1000; // 10 seconds
private static final int DISPLACEMENT = 10; // 10 meters
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private Location lastLocation;
private long lastTime;
LocationFinder.LocationUpdateListener locationUpdateListener;
private boolean isListenerRunning;
private LocationSettingsRequest locationSettingsRequest;
public GoogleServiceLocationProvider(Context base) {
super(base);
buildApiGoogleClient();
createLocationRequest();
buildLocationSettingsRequest();
}
private void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest);
locationSettingsRequest = builder.build();
}
public void checkLocationSettings() {
if(googleApiClient != null && locationSettingsRequest != null){
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
googleApiClient,
locationSettingsRequest
);
result.setResultCallback(this);
}
}
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult((Activity)getBaseContext(), REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
主要活动.class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
useGoogleLocationServiceAPI();
}
private void useGoogleLocationServiceAPI(){
googleServiceLocationProvider = new GoogleServiceLocationProvider(this);
googleServiceLocationProvider.checkLocationSettings();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode){
case PLAY_SERVICES_RESOLUTION_REQUEST:
switch(resultCode){
case RESULT_OK:
isGoogleLocationService = true;
useGoogleLocationServiceAPI();
break;
case RESULT_CANCELED:
Toast.makeText(this, getString(R.string.google_location_service_missing),
Toast.LENGTH_SHORT).show();
useAndroidLocationAPI();
break;
}
break;
case REQUEST_CHECK_SETTINGS:
switch(resultCode){
case RESULT_OK:
break;
case RESULT_CANCELED:
Toast.makeText(this, getString(R.string.location_off_message),
Toast.LENGTH_SHORT).show();
break;
}
break;
}
}
将上下文传递给每个类是一种选择。但我更喜欢保持这些类松散耦合,并使用EventBus
来发送和检索数据。因为它提供了一种集中的方式来通知对特定类型的事件感兴趣的软件组件。事件发布者的代码与接收事件的代码之间不存在直接耦合。设计良好的解耦系统将减少在发生任何更改时跨组件进行更改的需要。
该库可在此处获得:事件总线
这里有一个更简单的教程来解释相同的内容:如何使用绿色机器人事件总线库
更新
通过这行代码status.startResolutionForResult((Activity)getBaseContext(), /*...*/);
您假设已传递给构造函数GoogleServiceLocationProvider
的context
是一个可能并非总是如此的Activity
。如果您使用的是Service
怎么办?这条线(Activity)getBaseContext()
会抛出ClassCastException
.
如果你需要一个Activity
来确保你的GoogleServiceLocationProvider
拥有一切,为什么不在你的构造函数中只需要一个Activity
实例而不是一个Context
呢?
private Activity activity;
public GoogleServiceLocationProvider(Activity activity) {
super(activity.getContext());
this. activity = activity;
//...
}
稍后您将在onResult
方法中使用它,如下所示:
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
//...
status.startResolutionForResult(this.activity, REQUEST_CHECK_SETTINGS);
//...
}
现在回答你的第一个问题。
安卓事实
您始终在以某种方式context
可用的地方运行代码。
无论是Activity
、Service
、Application
、BoradcastReceiver
...您将可以直接/间接访问您的context
。
因此
最简单但更有效且分离的方法是将此context
作为对自定义类的引用传递。您可以在class
(依赖注入)中的某个位置保留对该context
的引用,以便以后使用它,但请注意泄漏。
一些代码
class MyClass {
//...
public void doSomethingWithTheContext (Context context) {
//...
context.doThis(/*...*/);
//...
}
}
用法
从Activity
,Application
,Service
...(全部延伸Context
)
myInstanceOfMyClass.doSomethingWithTheContext(this);
从Fragment
myInstanceOfMyClass.doSomethingWithTheContext(getActivity());
相关问题
在任何地方使用应用程序上下文?
您可以将Context
或Activity
对象传递给方法,如下所示:
public void startResolutionForResult(Context context) {
contex.showYourAlert();
}
要获取onActivityResult()
值,您也可以将它们作为参数传递,或者只是在Activity
中创建startResolutionForResult
方法。