我尝试在片段生命周期中实例化一个新类时出错

时间:2014-06-07 00:06:05

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

描述:我有两个课程如下,

伪代码

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)

更多细节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类。

1 个答案:

答案 0 :(得分:2)

  

B级(RookWork)的实例

RookWork是Activity。在Android中无法直接直接实例化活动。要创建新活动,您必须使用Intents。

如果正确理解,您需要一个活动实例,因为某些与Google Play服务相关的方法(例如startResolutionForResult())需要一个。

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

例如:

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