【问题标题】:Error when I try to instantiate a new class in fragment life cycle当我尝试在片段生命周期中实例化一个新类时出错
【发布时间】:2014-06-07 00:06:04
【问题描述】:

说明:I类如下,

伪代码

public class A extends Fragment {
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // Do something 
    return rootView;
   }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
     // Do something  
    } 



    public void onStart() {
        super.onStart()
    }

/* Etc more normal lifecycle callback methods.
 *
 */ 

// Second Class enclosed in first class
public class B extends FragmentActivity implements
        GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener {    

// Defined methods to be used by Class A.


}

现在我的问题是,当我尝试在 A 类中初始化 B 类时。就像B b = new B(); 我的崩溃线上我尝试初始化 B 类(我尝试在各种 Activity 回调方法中初始化 B 类,例如onActivityCreated(),OnCreateView()等都不起作用,具体报错如下:

空指针异常

android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:478)

& 在

android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141)

更多细节 Class A 被 MainActivity 调用,而 MainActivity 又用两个选项卡填充 ActionBar。最后这里是实际类 B 的代码和它调用的单独的异步类。

public class rookWork extends FragmentActivity implements
            GooglePlayServicesClient.ConnectionCallbacks,
            GooglePlayServicesClient.OnConnectionFailedListener {

        LocationClient mLocationClient = new LocationClient(this, this, this);

        public LocationClient setup() {

            return mLocationClient;
        }

        @Override
        public void onConnected(Bundle connectionHint) {
            Toast.makeText(getApplicationContext(), "Connected!",
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onDisconnected() {
            Toast.makeText(getApplicationContext(), "Disconnected!",
                    Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {

            /*
             * Google Play services can resolve some errors it detects. If the
             * error has a resolution, try sending an Intent to start a Google
             * Play services activity that can resolve error.
             */
            if (connectionResult.hasResolution()) {
                try {

                    // Start an Activity that tries to resolve the error
                    connectionResult
                            .startResolutionForResult(
                                    this,
                                    LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

                    /*
                     * Thrown if Google Play services canceled the original
                     * PendingIntent
                     */

                } catch (IntentSender.SendIntentException e) {

                    // Log the error
                    e.printStackTrace();
                }
            } else {

                // If no resolution is available, display a dialog to the user
                // with the error.
                showErrorDialog(connectionResult.getErrorCode());
            }
        }

        public void getAddress(View v) {
            // In Gingerbread and later, use Geocoder.isPresent() to see if a
            // geocoder is available.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD
                    && !Geocoder.isPresent()) {
                // No geocoder is present. Issue an error message
                Toast.makeText(getActivity(), R.string.no_geocoder_available,
                        Toast.LENGTH_LONG).show();
                return;
            }

            if (servicesConnected()) {
                // Get the current location
                Location currentLocation = mLocationClient.getLastLocation();

                // Turn the indefinite activity indicator on
                mActivityIndicator.setVisibility(View.VISIBLE);

                // Start the background task
                GetAddressTask getAddressTask = new GetAddressTask(
                        getActivity());
                getAddressTask.execute(currentLocation);
                // (new
                // GetAddressTask.GetAddressTask(this)).execute(currentLocation);
            } else {
                Toast.makeText(getActivity(), "servicesConnected() == false",
                        Toast.LENGTH_SHORT).show();
            }

        }

        private boolean servicesConnected() {
            // Check that Google Play services is available
            int resultCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(this);

            // If Google Play services is available
            if (ConnectionResult.SUCCESS == resultCode) {
                // In debug mode, log the status
                Log.d(LocationUtils.APPTAG,
                        getString(R.string.play_services_available));

                // Continue
                return true;
                // Google Play services was not available for some reason
            } else {
                // Display an error dialog
                Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
                        resultCode, this, 0);
                if (dialog != null) {
                    ErrorDialogFragment errorFragment = new ErrorDialogFragment();
                    errorFragment.setDialog(dialog);
                    errorFragment.show(getSupportFragmentManager(),
                            LocationUtils.APPTAG);
                }
                return false;
            }
        }

        private void showErrorDialog(int errorCode) {

            // Get the error dialog from Google Play services
            Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
                    errorCode, this,
                    LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);

            // If Google Play services can provide an error dialog
            if (errorDialog != null) {

                // Create a new DialogFragment in which to show the error dialog
                ErrorDialogFragment errorFragment = new ErrorDialogFragment();

                // Set the dialog in the DialogFragment
                errorFragment.setDialog(errorDialog);

                // Show the error dialog in the DialogFragment
                errorFragment.show(getSupportFragmentManager(),
                        LocationUtils.APPTAG);
            }
        }

        /**
         * Define a DialogFragment to display the error dialog generated in
         * showErrorDialog.
         */
        @SuppressLint("ValidFragment")
        public class ErrorDialogFragment extends DialogFragment {

            // Global field to contain the error dialog
            private Dialog mDialog;

            /**
             * Default constructor. Sets the dialog field to null
             */
            @SuppressLint("ValidFragment")
            public ErrorDialogFragment() {
                super();
                mDialog = null;
            }

            /**
             * Set the dialog to display
             * 
             * @param dialog
             *            An error dialog
             */
            public void setDialog(Dialog dialog) {
                mDialog = dialog;
            }

            /*
             * This method must return a Dialog to the DialogFragment.
             */
            public Dialog onCreateDialog(Bundle savedInstanceState) {
                return mDialog;
            }
        }

异步类:

/* 
 * Google Imports
 */

/*
 *  Android Imports
 */
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.os.AsyncTask;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

public class GetAddressTask extends AsyncTask<Location, Void, String> {
    Context mContext;
    String addressText;
    int test;

    public GetAddressTask(Context context) {
        super();
        mContext = context;
    }

    @Override
    protected String doInBackground(Location... params) {
        /*
         * Get a new geocoding service instance, set for localized addresses.
         * This example uses android.location.Geocoder, but other geocoders that
         * conform to address standards can also be used.
         */
        Geocoder geocoder = new Geocoder(mContext, Locale.getDefault());

        // Get the current location from the input parameter list
        Location location = params[0];

        // Create a list to contain the result address
        List<Address> addresses = null;

        // Try to get an address for the current location. Catch IO or network
        // problems.
        try {

            /*
             * Call the synchronous getFromLocation() method with the latitude
             * and longitude of the current location. Return at most 1 address.
             */
            addresses = geocoder.getFromLocation(location.getLatitude(),
                    location.getLongitude(), 1);

            // Catch network or other I/O problems.
        } catch (IOException exception1) {

            // Log an error and return an error message
            Log.e(LocationUtils.APPTAG,
                    mContext.getString(R.string.IO_Exception_getFromLocation));

            // print the stack trace
            exception1.printStackTrace();

            // Return an error message
            return (mContext.getString(R.string.IO_Exception_getFromLocation));

            // Catch incorrect latitude or longitude values
        } catch (IllegalArgumentException exception2) {

            // Construct a message containing the invalid arguments
            String errorString = mContext.getString(
                    R.string.illegal_argument_exception,
                    location.getLatitude(), location.getLongitude());
            // Log the error and print the stack trace
            Log.e(LocationUtils.APPTAG, errorString);
            exception2.printStackTrace();

            //
            return errorString;
        }
        // If the reverse geocode returned an address
        if (addresses != null && addresses.size() > 0) {

            // Get the first address
            Address address = addresses.get(0);

            // Format the first line of address
            String addressText = mContext.getString(
                    R.string.address_output_string,

                    // If there's a street address, add it
                    address.getMaxAddressLineIndex() > 0 ? address
                            .getAddressLine(0) : "",

                    // Locality is usually a city
                    address.getLocality(),

                    // The country of the address
                    address.getCountryName());

            // Return the text
            return addressText;

            // If there aren't any addresses, post a message
        } else {
            return mContext.getString(R.string.no_address_found);
        }
    }

    protected void onPostExecute(String result) {
        /*
         * Toast.makeText(mContext.getApplicationContext(), "Execution Done",
         * Toast.LENGTH_SHORT).show();
         */
        Toast.makeText(mContext.getApplicationContext(),
                "Params Length: " + Integer.toString(test), Toast.LENGTH_SHORT)
                .show();
    }
}

最后一点

如果我注释掉 B 类(RookWork)的实例化,一切都会运行良好。我以前能够使用地理编码器正常运行异步任务。然而,该设置并不涉及在 A 类中嵌入 B 类。

【问题讨论】:

    标签: java android asynchronous android-fragments google-geocoder


    【解决方案1】:

    B类(RookWork)的实例化

    RookWork 是Activity。 Activity 不能直接在 Android 中实例化。要创建新的 Activity,您必须使用 Intent。

    如果 In 理解正确,您需要一个 Activity 实例,因为某些 Google Play Services 相关方法(例如startResolutionForResult())需要一个。

    最简单的解决方案可能是将所有这些代码(即接口的实现)移动到片段本身,然后在需要 Activity 时使用getActivity()。它将返回 Fragment 当前附加到的 Activity。

    例如:

    public class A extends Fragment
        implements GooglePlayServicesClient.ConnectionCallbacks,
                   GooglePlayServicesClient.OnConnectionFailedListener
    {
        ...
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult)
        {
            ...
            connectionResult.startResolutionForResult(getActivity(), LocationUtils.CONNECTION_FAILURE_RESOLUTION_REQUEST);
            ...
        }
    ...
    

    【讨论】:

    • 你说得很有道理。你能解释一下我的问题吗?我需要 B 类保持原样,但是我必须调用它在 A 类中拥有的函数。有什么办法可以做到这一点......?你能举个例子吗?
    • 其实我想我想通了。谢谢你。最后一个问题?我正在尝试声明一个 LocationClient 变量,但不知道如何在扩展 Fragment 的类中执行此操作,而不是碎片活动任何想法。
    • @SeahawksRdaBest 您可以从 getActivity() 获取上下文。所以只需在onCreateView() 中调用new LocationClient(getActivity(), this, this);(假设片段本身实现了接口,正如我建议的那样)。
    • 我修复了应用程序,使其不再崩溃。唯一的问题是 GetAddressTask(asych 任务)完成后的 List 地址数组,我没有返回地址,即 params.length = 0。你知道为什么会发生这种情况吗?提前谢谢你。
    • ps 我得到了正确的纬度和经度。
    猜你喜欢
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    相关资源
    最近更新 更多