DialogFragment中的ListView不会保持最新

时间:2013-09-22 21:51:33

标签: android listview android-fragments android-arrayadapter back-stack

我对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>

1 个答案:

答案 0 :(得分:0)

将新项目添加到适配器后,您必须调用notifyDataSetChanged(),以便listview使用适配器中找到的新数据集刷新自身。您无需像在函数updateProfile

中那样更改适配器本身