非活动类中的Activity,Context方法和对象

时间:2017-01-31 18:35:27

标签: android android-activity

我正在制作一款使用设备传感器和位置的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
 |...

3 个答案:

答案 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); //... } 可用的代码。

contextActivityService还是Application ...您是否有直接/间接访问权限到你的BoradcastReceiver

<强>因此

最简单但更有效且解耦的方法是将此context作为对自定义类的引用传递。您可以在context(依赖注入)的某处保留对context的引用,以便稍后使用它,但要注意leaks

部分代码

class

<强>用法

来自class MyClass { //... public void doSomethingWithTheContext (Context context) { //... context.doThis(/*...*/); //... } } ActivityApplication ...(所有范围Service

Context

来自myInstanceOfMyClass.doSomethingWithTheContext(this);

Fragment

相关问题

Using Application context everywhere?

答案 2 :(得分:0)

您可以将ContextActivity个对象传递给方法,如下所示:

public void startResolutionForResult(Context context) {
    contex.showYourAlert();
}

要获取onActivityResult()值,您也可以将它们作为参数传递,或者只在startResolutionForResult内创建Activity方法。