newInstance()与自定义Java Generic?

时间:2014-06-24 07:37:15

标签: java android generics android-fragments

我正在开发我的第一个非教程'应用程序来增强和增强我的Android开发技能。

我一直在使用大量的Java Generics来增强可重用性和调试性,特别是因为我的许多片段对Question类的子类做了同样的事情。

我刚遇到了一个对我来说很新的传统模式,并且想知道我是否可以将它应用于Java中的通用类。

根据文本,应在Fragment类中创建newInstance(args,...)方法来处理 Intent Extras 片段参数的转换。

示例:

SomeActivity.class

@​O​v​e​r​r​i​d​e​
p​r​o​t​e​c​t​e​d​ ​F​r​a​g​m​e​n​t​ ​c​r​e​a​t​e​F​r​a​g​m​e​n​t​(​)​ ​{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​n​e​w​ ​ObjectF​r​a​g​m​e​n​t​(​)​;​

 ​ ​ ​ ​U​U​I​D​ ​object​I​d​ ​=​ ​(​U​U​I​D​)​g​e​t​I​n​t​e​n​t​(​)​
 ​ ​ ​ ​ ​ ​ ​ ​.​g​e​t​S​e​r​i​a​l​i​z​a​b​l​e​E​x​t​r​a​(Object​F​r​a​g​m​e​n​t​.​E​X​T​R​A​_​OBJECT_​I​D​)​;​

 ​ ​ ​ ​r​e​t​u​r​n​ ​Object​F​r​a​g​m​e​n​t​.​n​e​w​I​n​s​t​a​n​c​e​(object​I​d​)​;​
}​

ObjectFragment.class

p​u​b​l​i​c​ ​s​t​a​t​i​c​ ObjectF​r​a​g​m​e​n​t​ ​n​e​w​I​n​s​t​a​n​c​e​(​U​U​I​D​ ​object​I​d​)​ ​{​
 ​ ​ ​ ​B​u​n​d​l​e​ ​a​r​g​s​ ​=​ ​n​e​w​ ​B​u​n​d​l​e​(​)​;​
 ​ ​ ​ ​a​r​g​s​.​p​u​t​S​e​r​i​a​l​i​z​a​b​l​e​(​E​X​T​R​A​_​C​R​I​M​E​_​I​D​,​ ​object​I​d​)​;​

 ​ ​ ​ ​ObjectF​r​a​g​m​e​n​t​ ​f​r​a​g​m​e​n​t​ ​=​ ​n​e​w​ ​ObjectF​r​a​g​m​e​n​t​(​)​;​
 ​ ​ ​ ​f​r​a​g​m​e​n​t​.​s​e​t​A​r​g​u​m​e​n​t​s​(​a​r​g​s​)​;​

 ​ ​ ​ ​r​e​t​u​r​n​ ​f​r​a​g​m​e​n​t​;​
}​

摘录自:Brian Hardy。 “Android编程:大书呆子牧场指南。”

但是使用Java Generics的案例呢?

我正在处理的代码:

QuestionListActivity.class

public class QuestionListActivity extends SingleFragmentActivity {


    // CONSTANTS
    public static final String EXTRA_FRAGMENT_TYPE = "com.renaissanceartsmedia.flashcard.editquestionactivity.fragment";
    public static final String EXTRA_ACTIVITY_TITLE = "ListQuestionActivity.EXTRA_ACTIVITY_TITLE";
    public static final String TAG = "QuestionListActivity";

    // Member Properties
    QuestionType mFragmentType;

    @Override
    protected Fragment createFragment() {

        mFragmentType = (QuestionType) getIntent().getSerializableExtra(EXTRA_FRAGMENT_TYPE);
        System.out.println("mFragmentType: " + mFragmentType);

        // Switch on Enumeration
        switch (mFragmentType) {

            case MULTIPLE_ANSWER_QUESTION:
            case MULTIPLE_CHOICE_QUESTION:
            case TRUE_FALSE_QUESTION:

                // PREVIOUS METHOD
                //return new QuestionListFragment<MultipleAnswerQuestion>();

                // Attempting to refactor to newInstance(Bundle args)
                return QuestionListFragment<MultipleAnswerQuestion>.newInstance(getIntent().getExtras()); // ERROR

            case MATCHING_QUESTION:
                return new QuestionListFragment<MatchingQuestion>();

            case BLANK_QUESTION:
                //return new BQFragment();
                return new QuestionListFragment<BlankQuestion>();
            default:
                return new QuestionListFragment<Question>();
        }

    }
}

目前,我从QuestionListFragment的onCreate()方法中获取Extras。我知道如果转换到newInstance()约定应该与Java Generics一起使用,我将删除此代码。

QuestionListFragment.class

    public class QuestionListFragment<E extends Question> extends ListFragment implements QuestionDialogInterface {

        // Constants
        public static final String TAG = "QuestionListFragement";
        public static final String DIALOG_TITLE = "QuestionListFragment.DIALOG_TITLE";
        public static final String DIALOG_MESSAGE = "QuestionListFragment.DIALOG_MESSAGE";
        public static final String QUESTION_TYPE = "QUESTION_TYPE";
        private static final int DIALOG_FRAGMENT = 1;

        // Member Properties
        Flashcard mFlashcard;
        QuestionType mQuestionType;
        String mActivityTitle;
        ArrayList<E> mQuestions;
        DialogFragment mDialogFragment;

// SOMETHING LIKE THIS???
        @SuppressWarnings({ "unchecked", "rawtypes" })
        public static QuestionListFragment<? extends Question> newInstance(Bundle args) {
            // Create a new instance of QuestionListFragment<? extends Question>
            QuestionListFragment<? extends Question> fragment = new QuestionListFragment();

            // Set the arguments
            fragment.setArguments(args);

            // Return the Fragment
            return fragment;
        }

        @SuppressWarnings("unchecked")
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG,"Enter onCreate(Bundle savedInstanceState)");
            // Enable Options Menu
            setHasOptionsMenu(true);

            // Create the ActionBar 'UP' Button
            getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);

            // The Intent Extras
            Bundle extras = getActivity().getIntent().getExtras();

            // Extract the Flashcard from the extras
            UUID flashcardId = (UUID) extras.getSerializable(Flashcard.EXTRA_FLASHCARD_ID);
            mFlashcard = FlashcardStore.get(getActivity()).getFlashcard(flashcardId);
            mQuestionType = (QuestionType) extras.getSerializable(EditQuestionActivity.EXTRA_FRAGMENT_TYPE);
            mActivityTitle = extras.getString(QuestionListActivity.EXTRA_ACTIVITY_TITLE);


            // Get a Container of Multiple Answer Questions
            mQuestions = (ArrayList<E>) mFlashcard.getQuestions(mQuestionType);

            // Set the Title of the Fragment's Activity
            getActivity().setTitle(mActivityTitle);

            // Create a list 
            ListItemLayoutAdapter adapter = new ListItemLayoutAdapter(mQuestions);

            // Set the adapter for the list
            setListAdapter(adapter);
            Log.d(TAG,"Exit onCreate(Bundle savedInstanceState)");
        }
    ....
    }

Android Fragments和Java Generics的最佳实践是什么?有人可以描述它们是什么,为什么要使用它们。如果应该使用newInstance(),请通过提供正确的声明语法来帮助我修复错误:

// Attempting to refactor to newInstance(Bundle args)
 return QuestionListFragment<MultipleAnswerQuestion>.newInstance(getIntent().getExtras()); // ERROR

3 个答案:

答案 0 :(得分:6)

    public static <T extends Question> QuestionListFragment<T> newInstance(Bundle args) {
        // Create a new instance of QuestionListFragment<? extends Question>
        QuestionListFragment<T> fragment = new QuestionListFragment<T>();

        // Set the arguments
        fragment.setArguments(args);

        // Return the Fragment
        return fragment;
    }

然后调用它:

    QuestionListFragment.<MultipleAnswerQuestion>newInstance(getIntent().getExtras()‌​);

答案 1 :(得分:1)

 public static <T extends BaseFragment> T getInstance (Class<T> mClass, Bundle args) {
    try {
        T instance = mClass.newInstance();
        instance.setArguments(args);
        return instance;
    } catch (java.lang.InstantiationException | IllegalAccessException e) {
        /**
         * Error thrown
         */
    }

    return null;
}

较短的版本。 干杯

答案 2 :(得分:0)

如果您的目的是扩展具有某些自定义行为的“ BaseFragment”,以便在孩子之间共享它,那么我将这样做:

使用通用方法为实例孩子创建BaseFragment

public abstract class BaseFragment extends Fragment {

    public static <T extends NewReportFragment> T newInstance(Delegate delegate, Class<T> classInstance) {
        T fragment = null;
        try {
            fragment = classInstance.newInstance();
            fragment.setDelegate(delegate);
        } catch (java.lang.InstantiationException e) {
            e.printStackTrace();
        } catch (java.lang.IllegalAccessException e) {
            e.printStackTrace();
        }
        return fragment;
    }
}

您可以这样实例化子代:

FirstFragment aFragment = BaseFragment.newInstance(this, FirstFragment.class);

BaseFragment的子级必须包含默认构造函数才能进行通用实例化。

public static class ConfirmationFragment extends NewReportFragment {
        public ConfirmationFragment() { }
}

注意:委托只是与活动中的片段进行交互的界面。如果您需要了解代表,请查看this