0

我在 DialogFragments 和 backstacks 上遇到了一个非常烦人的问题。

我有一个承载 ActiveMenuFragment 的 MainActivity。

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,但没有。每次我通过 backstack 返回它时,它都会显示相同的 8 个旧动作。

   /**
    * 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 对象还包含与用户相关的操作字典和其他信息。宿主活动应该保留并修改它,还是应该由 ActiveMenu 片段处理它?

4

1 回答 1

0

Once you have added the new item to the adapter you have to call notifyDataSetChanged() so that the listview refreshes itself with the new set of data found in the adapter. You need not change the adapter itself as you are doing in the function updateProfile

于 2013-09-22T22:39:32.757 回答