我正在制作一款使用设备传感器和位置的Android应用。来自两个来源的数据将用于计算有关方向的一些事情。到目前为止,我创建了两个非活动类,一个用于传感器管理,另一个用于位置管理。问题是当我想要使用需要Activity或Context的东西时,例如:通过调用startResolutionForResult()
来显示对话框,并在onActivityResult()
中检查结果。 startResolutionForResult()
需要Activity才能显示对话框。
解决这个问题的最佳方法是什么?我决定使用上下文作为每个非活动类的字段成员,但我不确定它是否是最佳选择。
更新 这是我的代码的一部分,我正在努力。
在onCreate()
方法中,我调用checkLocationSettings()
方法检查位置是否已开启。 Then onResult()
回调会触发,我可以根据位置设置确定要执行的操作。当位置关闭时,它会显示由
status.startResolutionForResult((Activity)getBaseContext(), REQUEST_CHECK_SETTINGS)
用户决策的结果可在onActivityResult()
中获得,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;
}
}
是MainActivity.class的一部分
一切都像魅力一样,但我特别关注(Activity)getBaseContext()。
GoogleServiceLocationProvider.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;
}
}
MainActivity.class
|_
RandomnameFile1.KnownFormat1
|_
RandomnameFile2.KnownFormat2
|_
RandomnameFile3.KnownFormat3
|...
答案 0 :(得分:2)
将上下文传递给每个类是一个选项。但我更喜欢保持这些类松散耦合,并使用EventBus
来发送和检索数据。因为它提供了一种集中的方式来通知对特定类型的事件感兴趣的软件组件。事件的发布者的代码与接收它的代码之间不存在直接耦合。设计良好的解耦系统将减少在组件发生变化时对组件进行更改的需要。
图书馆可在此处找到:EventBus
这是一个更简单的教程,解释相同:How to use the greenrobot EventBus library
答案 1 :(得分:1)
<强>更新强>
通过这行代码status.startResolutionForResult((Activity)getBaseContext(), /*...*/);
,您假设已传递给构造函数context
的{{1}}为GoogleServiceLocationProvider
,但可能并非总是如此。如果您使用Activity
怎么办?此行Service
会抛出(Activity)getBaseContext()
。
如果您需要ClassCastException
以确保Activity
拥有所有内容,为什么不要只需GoogleServiceLocationProvider
个实例而不是Activity
在你的构造函数?
Context
您稍后会在private Activity activity;
public GoogleServiceLocationProvider(Activity activity) {
super(activity.getContext());
this. activity = activity;
//...
}
方法中使用它,如下所示:
onResult
现在回答你的第一个问题。
Android事实
您总是以某种方式运行@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
//...
status.startResolutionForResult(this.activity, REQUEST_CHECK_SETTINGS);
//...
}
可用的代码。
是context
,Activity
,Service
还是Application
...您是否有直接/间接访问权限到你的BoradcastReceiver
。
<强>因此强>
最简单但更有效且解耦的方法是将此context
作为对自定义类的引用传递。您可以在context
(依赖注入)的某处保留对context
的引用,以便稍后使用它,但要注意leaks。
部分代码
class
<强>用法强>
来自class MyClass {
//...
public void doSomethingWithTheContext (Context context) {
//...
context.doThis(/*...*/);
//...
}
}
,Activity
,Application
...(所有范围Service
)
Context
来自myInstanceOfMyClass.doSomethingWithTheContext(this);
Fragment
相关问题
答案 2 :(得分:0)
您可以将Context
或Activity
个对象传递给方法,如下所示:
public void startResolutionForResult(Context context) {
contex.showYourAlert();
}
要获取onActivityResult()
值,您也可以将它们作为参数传递,或者只在startResolutionForResult
内创建Activity
方法。