【问题标题】:getActivity() returns null - The second time I open the fragmentgetActivity() 返回 null - 我第二次打开片段
【发布时间】:2016-02-17 21:29:54
【问题描述】:

当我按下按钮时,ShowActivities 片段正在被实例化。我第一次按下它时一切正常。这就是我在 logCat 中得到的:

11-16 23:41:12.560 25874-25874/name.company.newapp E/onCreate: getActivity() == null: false
11-16 23:41:12.560 25874-25874/name.company.newapp E/onCreate: Hash: 1036405628
11-16 23:41:12.570 25874-25874/name.company.newapp E/onCreateView: getActivity() == null: false
11-16 23:41:12.570 25874-25874/name.company.newapp E/onCreateView: Hash: 1036405628
11-16 23:41:12.630 25874-25874/name.company.newapp E/onConnected: getActivity() == null: false
11-16 23:41:12.630 25874-25874/name.company.newapp E/onConnected: Hash: 1036405628

一切正常。我按后退键并返回到上一个片段。现在我再次点击按钮打开ShowActivities片段,现在logCat返回的是:

11-16 23:41:13.890 25874-25874/name.company.newapp E/onCreate: getActivity() == null: false
11-16 23:41:13.890 25874-25874/name.company.newapp E/onCreate: Hash: 252302789
11-16 23:41:13.890 25874-25874/name.company.newapp E/onCreateView: getActivity() == null: false
11-16 23:41:13.890 25874-25874/name.company.newapp E/onCreateView: Hash: 252302789
11-16 23:41:13.900 25874-25874/name.company.newapp E/onConnected: getActivity() == null: true
11-16 23:41:13.900 25874-25874/name.company.newapp E/onConnected: Hash: 1036405628

onConnected 在同一个片段上被调用,尽管 onCreate 正在创建另一个片段。

ShowActivity 片段

    public class ShowActivities extends Fragment implements
            GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {


        public ShowActivities() {
        }

        private static GoogleApiClient googleClient;
        private Location mLastLocation;
        private PendingResult<LocationSettingsResult> result;
        private LocationRequest locationRequest;



        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
         Log.e("onCreate"," "+(getActivity() == null));
            if (googleClient==null) {
                googleClient = new GoogleApiClient.Builder(getActivity())
                        .addApi(LocationServices.API)
                        .addConnectionCallbacks(this)
                        .addOnConnectionFailedListener(this)
                        .build();
            }
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
 super.onCreateView(inflater, container, savedInstanceState);
Log.e("onCreateView"," "+(getActivity() == null));
            // Defines the xml file for the fragment
            View view = inflater.inflate(R.layout.upload_activity_fragment, container, false);
            return view;
        }


        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {

        }


        @Override
        public void onConnected(Bundle bundle) {
            Log.e("onConnected"," "+(getActivity() == null));
            locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

            builder.setAlwaysShow(true);
            result = LocationServices.SettingsApi.checkLocationSettings(googleClient, builder.build());

            if (result != null) {
                result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
                    @Override
                    public void onResult(LocationSettingsResult locationSettingsResult) {
                        final Status status = locationSettingsResult.getStatus();
                        switch (status.getStatusCode()) {
                            case LocationSettingsStatusCodes.SUCCESS:
                                // All location settings are satisfied. The client can initialize location
                                // requests here.

                                break;
                            case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                                // Location settings are not satisfied. But could be fixed by showing the user
                                // a optionsDialog.
                                try {
                                    // Show the optionsDialog by calling startResolutionForResult(),
                                    // and check the result in onActivityResult().
                                    if (status.hasResolution()) {
                                        status.startResolutionForResult(getActivity(), 1000);
                                        Log.e("location", "Resolution");
                                    }
                                } catch (IntentSender.SendIntentException e) {
                                    // Ignore the error.
                                    Log.e("location", "Resolution2");
                                }
                                break;
                            case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                                // Location settings are not satisfied. However, we have no way to fix the
                                // settings so we won't show the optionsDialog.
                                break;
                        }
                    }
                });
            }
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if ((resultCode == Activity.RESULT_OK) && (requestCode == 1000)) {
                mLastLocation = LocationServices.FusedLocationApi.getLastLocation(googleClient);
            }
        }

        @Override
        public void onConnectionSuspended(int i) {

        }

        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {

        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e("location", "finally");
        }

        @Override
        public void onResume() {
            super.onResume();

        }

        @Override
        public void onPause() {
            super.onPause();
            if (googleClient!=null) {
                googleClient = null;
            }
        }

    }

这已经解决了。退出片段后,我修改了 onPause 以使 googleClient 为空。

【问题讨论】:

  • 为什么不在执行事务之前初始化fragment?
  • 我不认为这是问题
  • 是FragmentActivities Fragment 还是Activity?
  • 一个片段。我在整个项目中只有一项活动。
  • 从异常堆栈跟踪开始,了解问题在片段生命周期中的哪个位置。

标签: android android-fragments google-maps-api-3


【解决方案1】:

首先,请把onCreateView中的super方法调用改为调用super.onCreateView(...)。

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Defines the xml file for the fragment
    View view = inflater.inflate(R.layout.upload_activity_fragment, container, false);
    return view;
}

然后把这块移到onActivityCreated(...)

client = new NightAssetRestClient(getActivity());
    locationQueries = new LocationQueries(getActivity());
    if (googleClient==null) {
        googleClient = new GoogleApiClient.Builder(getActivity())
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

尽管如此,您仍然需要在 onConnect(...) 中检查 null,因为即使底层 Activity 被销毁,异步进程也可以持有此 Fragment 的引用。

在 onCreate 方法中添加行 setRetainInstance(boolean) 可能会有所帮助。

【讨论】:

  • 改变它。对不起。我通常在其他片段中什么都没有。我添加它是因为我认为它可以解决问题。我现在修改为super.onCreateView(inflater, container, savedInstanceState);
  • 问题不存在。我不知道这是怎么回事。
  • getActivity(..) 无论如何都不能保证返回一个值。我编辑的答案可能有助于缓解问题。
  • 这不好,伙计。所以如果你检查onCreate 中的getActivity() 是真的,但如果你检查onConnected 是假的。这是怎么发生的?
  • 片段和活动有不同的生命周期,它们不同步。即使在 Activity 被销毁并重新创建之后,也可以保留一个 Fragment 实例。 getActivity() 返回 null 是正常的。
【解决方案2】:

尝试先通过TAG获取占位符中的Fragment实例,如果没有之前的实例,则创建实例。

    Fragment ShowActivities = getFragmentManager().getFragmentByTag(YOUR_TAG);
    if (showActivities == null) {
        showActivities = new ShowActivities();
        getFragmentManager().beginTransaction()
                .replace(R.id.your_placeholder, showActivities, YOUR_TAG)
                .addToBackStack(null)
                .commit();
    }

【讨论】:

  • 占位符中总有一些东西。我对所有片段使用相同的占位符
  • 然后你可以在replace方法中使用一个Tag来识别这个实例。
  • 好的,我现在尝试修改它,但是这将如何解决问题?
  • 我怀疑您正在调用 Fragment 实例的方法,该方法实际上并未添加到 Activity 中。如果这个技巧不起作用,你将不得不粘贴你的 Fragment 代码。
  • 对不起,没有足够的信息来说明问题所在,必须看看Fragment的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
  • 2012-07-22
  • 2013-03-30
  • 1970-01-01
  • 2014-12-27
相关资源
最近更新 更多