有警告但程序仍然运行:碎片应该是静态的,以便它们可以由系统重新实例化

时间:2016-12-12 15:10:51

标签: java android

我看到这个警告: enter image description here

这是代码行警告: https://github.com/donhuvy/temp/blob/master/app/src/main/java/com/deitel/addressbook/DetailFragment.java#L126

// Fragment subclass that displays one contact's details
package com.deitel.addressbook;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.deitel.addressbook.data.DatabaseDescription.Contact;

public class DetailFragment extends Fragment
        implements LoaderManager.LoaderCallbacks<Cursor> {

    // callback methods implemented by MainActivity
    public interface DetailFragmentListener {
        void onContactDeleted(); // called when a contact is deleted

        // pass Uri of contact to edit to the DetailFragmentListener
        void onEditContact(Uri contactUri);
    }

    private static final int CONTACT_LOADER = 0; // identifies the Loader

    private DetailFragmentListener listener; // MainActivity
    private Uri contactUri; // Uri of selected contact

    private TextView nameTextView; // displays contact's name
    private TextView phoneTextView; // displays contact's phone
    private TextView emailTextView; // displays contact's email
    private TextView streetTextView; // displays contact's street
    private TextView cityTextView; // displays contact's city
    private TextView stateTextView; // displays contact's state
    private TextView zipTextView; // displays contact's zip

    // set DetailFragmentListener when fragment attached
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        listener = (DetailFragmentListener) context;
    }

    // remove DetailFragmentListener when fragment detached
    @Override
    public void onDetach() {
        super.onDetach();
        listener = null;
    }

    // called when DetailFragmentListener's view needs to be created
    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        setHasOptionsMenu(true); // this fragment has menu items to display

        // get Bundle of arguments then extract the contact's Uri
        Bundle arguments = getArguments();

        if (arguments != null)
            contactUri = arguments.getParcelable(MainActivity.CONTACT_URI);

        // inflate DetailFragment's layout
        View view =
                inflater.inflate(R.layout.fragment_detail, container, false);

        // get the EditTexts
        nameTextView = (TextView) view.findViewById(R.id.nameTextView);
        phoneTextView = (TextView) view.findViewById(R.id.phoneTextView);
        emailTextView = (TextView) view.findViewById(R.id.emailTextView);
        streetTextView = (TextView) view.findViewById(R.id.streetTextView);
        cityTextView = (TextView) view.findViewById(R.id.cityTextView);
        stateTextView = (TextView) view.findViewById(R.id.stateTextView);
        zipTextView = (TextView) view.findViewById(R.id.zipTextView);

        // load the contact
        getLoaderManager().initLoader(CONTACT_LOADER, null, this);
        return view;
    }

    // display this fragment's menu items
    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.fragment_details_menu, menu);
    }

    // handle menu item selections
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_edit:
                listener.onEditContact(contactUri); // pass Uri to listener
                return true;
            case R.id.action_delete:
                deleteContact();
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    // delete a contact
    private void deleteContact() {
        // use FragmentManager to display the confirmDelete DialogFragment
        confirmDelete.show(getFragmentManager(), "confirm delete");
    }

    // DialogFragment to confirm deletion of contact
    private final DialogFragment confirmDelete =
            new DialogFragment() {
                // create an AlertDialog and return it
                @Override
                public Dialog onCreateDialog(Bundle bundle) {
                    // create a new AlertDialog Builder
                     AlertDialog.Builder builder =
                            new AlertDialog.Builder(getActivity());

                    builder.setTitle(R.string.confirm_title);
                    builder.setMessage(R.string.confirm_message);

                    // provide an OK button that simply dismisses the dialog
                    builder.setPositiveButton(R.string.button_delete,
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(
                                        DialogInterface dialog, int button) {

                                    // use Activity's ContentResolver to invoke
                                    // delete on the AddressBookContentProvider
                                    getActivity().getContentResolver().delete(
                                            contactUri, null, null);
                                    listener.onContactDeleted(); // notify listener
                                }
                            }
                    );

                    builder.setNegativeButton(R.string.button_cancel, null);
                    return builder.create(); // return the AlertDialog
                }
            };

    // called by LoaderManager to create a Loader
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        // create an appropriate CursorLoader based on the id argument;
        // only one Loader in this fragment, so the switch is unnecessary
        CursorLoader cursorLoader;

        switch (id) {
            case CONTACT_LOADER:
                cursorLoader = new CursorLoader(getActivity(),
                        contactUri, // Uri of contact to display
                        null, // null projection returns all columns
                        null, // null selection returns all rows
                        null, // no selection arguments
                        null); // sort order
                break;
            default:
                cursorLoader = null;
                break;
        }

        return cursorLoader;
    }

    // called by LoaderManager when loading completes
    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        // if the contact exists in the database, display its data
        if (data != null && data.moveToFirst()) {
            // get the column index for each data item
            int nameIndex = data.getColumnIndex(Contact.COLUMN_NAME);
            int phoneIndex = data.getColumnIndex(Contact.COLUMN_PHONE);
            int emailIndex = data.getColumnIndex(Contact.COLUMN_EMAIL);
            int streetIndex = data.getColumnIndex(Contact.COLUMN_STREET);
            int cityIndex = data.getColumnIndex(Contact.COLUMN_CITY);
            int stateIndex = data.getColumnIndex(Contact.COLUMN_STATE);
            int zipIndex = data.getColumnIndex(Contact.COLUMN_ZIP);

            // fill TextViews with the retrieved data
            nameTextView.setText(data.getString(nameIndex));
            phoneTextView.setText(data.getString(phoneIndex));
            emailTextView.setText(data.getString(emailIndex));
            streetTextView.setText(data.getString(streetIndex));
            cityTextView.setText(data.getString(cityIndex));
            stateTextView.setText(data.getString(stateIndex));
            zipTextView.setText(data.getString(zipIndex));
        }
    }

    // called by LoaderManager when the Loader is being reset
    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }
}

帮我修复此警告

3 个答案:

答案 0 :(得分:0)

如错误所示,每个片段都应该有一个空构造函数,如果应用程序移动到后台/前台,系统将使用它来重新创建片段。

在您的情况下,您正在使用内部类,并直接调用空构造函数。

这没有错,但是为了防止错误使用片段构造函数,在这些构造函数中你设置了片段的参数,当系统重新创建片段时这些参数会丢失,我认为lint引发了这个警告,只是为了确保你理解使用这样的片段可能有风险。

仅供参考:这是一个关于如何以“lint”方式使用它的演示:))https://developer.android.com/reference/android/app/DialogFragment.html

答案 1 :(得分:0)

在与@danypata相同的行中,您需要在重新创建片段时可以访问构造函数。我认为你必须使它静止以消除警告并正确使用碎片。

答案 2 :(得分:0)

我会这样做的。无需DialogFragment

private void deleteContact() {
     AlertDialog.Builder builder =
            new AlertDialog.Builder(getActivity())
    .setTitle(R.string.confirm_title)
    .setMessage(R.string.confirm_message)
    .setPositiveButton(R.string.button_delete,
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(
                    DialogInterface dialog, int button) {

                // use Activity's ContentResolver to invoke
                // delete on the AddressBookContentProvider
                getActivity().getContentResolver().delete(
                        contactUri, null, null);
                listener.onContactDeleted(); // notify listener
            }
        }
    ).setNegativeButton(R.string.button_cancel, null)
    .create();
}