我正在开发我的第一个非教程'应用程序来增强和增强我的Android开发技能。
我一直在使用大量的Java Generics来增强可重用性和调试性,特别是因为我的许多片段对Question
类的子类做了同样的事情。
我刚遇到了一个对我来说很新的传统模式,并且想知道我是否可以将它应用于Java中的通用类。
根据文本,应在Fragment类中创建newInstance(args,...)
方法来处理 Intent Extras 到片段参数的转换。
示例:
SomeActivity.class
@Override
protected Fragment createFragment() {
return new ObjectFragment();
UUID objectId = (UUID)getIntent()
.getSerializableExtra(ObjectFragment.EXTRA_OBJECT_ID);
return ObjectFragment.newInstance(objectId);
}
ObjectFragment.class
public static ObjectFragment newInstance(UUID objectId) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_CRIME_ID, objectId);
ObjectFragment fragment = new ObjectFragment();
fragment.setArguments(args);
return fragment;
}
摘录自: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
答案 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。