我对DialogFragments和Backstacks有一个非常烦人的问题。
我有一个MainActivity,它承载一个ActiveMenuFragment。
ActiveMenuFragment有一个启动DialogFragmentActionSelector的按钮(所有方法都是从MainActivity强制接口方法运行的):
/**
* Opens the action selection dialog, so the user may pick an action to
* begin.
*/
@Override
public void openActionSelector() {
actionSelectorFragment = DialogFragmentActionSelector.newInstance();
Bundle args = new Bundle();
args.putSerializable("Profile", currentProfile);
actionSelectorFragment.setArguments(args);
FragmentTransaction ft = this.getFragmentManager().beginTransaction();
ft.addToBackStack("Action Selector");
actionSelectorFragment.show(ft, "Action Selector");
}
此片段显示带有操作列表的ListView。此时一切都很好。甚至以前添加的新操作也将显示在此处。现在,如果用户想要定义一个新动作,他们按下DialogFragment中的一个按钮,启动DialogFragmentDefineNewAction:
/**
* Opens the action selection dialog, so the user may pick an action to
* begin.
*/
@Override
public void openActionSelector() {
actionSelectorFragment = DialogFragmentActionSelector.newInstance();
Bundle args = new Bundle();
args.putSerializable("Profile", currentProfile);
actionSelectorFragment.setArguments(args);
FragmentTransaction ft = this.getFragmentManager().beginTransaction();
ft.addToBackStack("Action Selector");
actionSelectorFragment.show(ft, "Action Selector");
}
在用户输入新操作的数据后,他们点击确认按钮,这是支持更新前一个片段(DialogFragmenActionSelector)中的ListView,但没有。每次我通过靠背堆返回它时,它都会显示相同的旧动作。
/**
* Takes the action defined in the DefineNewAction fragment and adds it to
* the user dictionary.
*/
@Override
public void addNewActionToDictionary(Action toAdd) {
currentProfile.getDictionary().addDefinition(toAdd);
actionSelectorFragment.updateProfile(currentProfile);
}
作为参考,这里是整个DialogFragmentActionSelector,其中包含ArrayAdapter:
public class DialogFragmentActionSelector extends DialogFragment implements
OnClickListener {
private EditText searchBar;
private Button defineNewActionBtn;
private ListView actionList;
private UserProfile user;
private ListViewInterface mInterface;
private ActionsAdapter adapter;
public interface ListViewInterface {
void openDefineNewAction();
void setActiveMenuActionBar(String action);
}
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof ListViewInterface) {
mInterface = (ListViewInterface) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implement ListViewInterface");
}
}
/**
* Constructor for the fragment.
*
* @return
*/
public static DialogFragmentActionSelector newInstance() {
DialogFragmentActionSelector dfm = new DialogFragmentActionSelector();
return dfm;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View toReturn = inflater.inflate(
R.layout.fragment_action_selector_layout, container, false);
user = (UserProfile) this.getArguments().get("Profile");
searchBar = (EditText) toReturn.findViewById(R.id.action_search_bar);
searchBar.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable arg0) {
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
adapter.updateList();
adapter.getFilter().filter(arg0);
}
});
defineNewActionBtn = (Button) toReturn
.findViewById(R.id.define_new_action);
defineNewActionBtn.setOnClickListener(this);
actionList = (ListView) toReturn.findViewById(R.id.actions_list);
ArrayList<Action> allActions = user.getDictionary().getAllActions();
adapter = new ActionsAdapter(this.getActivity(),
android.R.layout.simple_list_item_1, allActions, inflater);
actionList.setAdapter(adapter);
actionList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View clickedView,
int index, long id) {
Action selectedAction = (Action) parent.getItemAtPosition(index);
mInterface.setActiveMenuActionBar(selectedAction.getActionName());
dismiss();
}
});
return toReturn;
}
public void updateProfile(UserProfile updatedProfile) {
user = updatedProfile;
ArrayList<Action> allActions = user.getDictionary().getAllActions();
adapter = new ActionsAdapter(this.getActivity(),
android.R.layout.simple_list_item_1, allActions, getActivity()
.getLayoutInflater());
actionList.setAdapter(adapter);
actionList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View clickedView,
int index, long id) {
Action selectedAction = (Action) parent.getItemAtPosition(index);
mInterface.setActiveMenuActionBar(selectedAction.getActionName());
dismiss();
}
});
// this.updateListView();
}
private void updateListView() {
adapter.updateList();
}
// TODO FIX CONSTRUCTOR. UPON RETURNING, IT REVERTS TO DEFAULT 8 ACTIONS
// RATHER THAN NEW ONES.
private class ActionsAdapter extends ArrayAdapter<Action> implements
Filterable {
LayoutInflater inflater;
ArrayList<Action> actionsList;
public ActionsAdapter(Context context, int resId,
ArrayList<Action> objects, LayoutInflater inflater) {
super(context, resId, objects);
this.actionsList = objects;
this.inflater = inflater;
}
@Override
public int getCount() {
return actionsList.size();
}
@Override
public Action getItem(int position) {
return actionsList.get(position);
}
@Override
public long getItemId(int position) {
return this.getItem(position).hashCode();
}
public void updateList() {
ArrayList<Action> allActions = user.getDictionary().getAllActions();
actionsList = allActions;
notifyDataSetInvalidated();
// notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Action toWrap = actionsList.get(position);
if (convertView == null) {
holder = new ViewHolder();
convertView = inflater.inflate(
R.layout.listview_row_action_selector, parent, false);
holder.actionName = (TextView) convertView
.findViewById(R.id.action_title);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.actionName.setText(toWrap.getActionName());
return convertView;
}
private class ViewHolder {
TextView actionName;
}
/**
* Filters the adapter's database.
*/
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
ArrayList<Action> matchingActions = new ArrayList<Action>();
for (int i = 0; i < actionsList.size(); i++) {
Action actionToCheck = actionsList.get(i);
ArrayList<String> actionTags = actionToCheck.getTags();
String searchQuery = constraint.toString();
boolean foundMatch = false;
int k = 0;
int tagSize = actionTags.size();
if (tagSize != 0) {
while (!foundMatch && k < tagSize) {
if (actionTags.get(k).contains(searchQuery)) {
matchingActions.add(actionToCheck);
foundMatch = true;
}
k++;
}
}
}
results.count = matchingActions.size();
results.values = matchingActions;
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// actionsList.clear();
actionsList = (ArrayList<Action>) results.values;
adapter.notifyDataSetChanged();
}
};
return filter;
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.define_new_action:
mInterface.openDefineNewAction();
break;
default:
break;
}
}
public void addNewActionToDictionary(Action toAdd) {
user.getDictionary().addDefinition(toAdd);
adapter.add(toAdd);
adapter.updateList();
}
}
我应该使用notifyDataSetChanged()还是无效?因为它不适用于我的适配器。
如果我关闭所有对话框并再次打开它们,更新的操作将显示在列表视图中。为什么呢?
此外,我觉得我的工作效率低下,使事情变得比他们需要的更复杂。 UserProfile对象还包含Actions Dictionary和与用户相关的其他信息。主机活动是否应该保留并修改它,或者ActiveMenu片段是否应该处理它?</ p>
答案 0 :(得分:0)
将新项目添加到适配器后,您必须调用notifyDataSetChanged()
,以便listview使用适配器中找到的新数据集刷新自身。您无需像在函数updateProfile