2

Какой лучший шаблон для этого. Я сделал некоторое обходное решение, но я чувствую, что это плохая модель.Обновление RecyclerView из DialogFragment и основной деятельности

Мой сценарий.

У меня Основной вид деятельности

MainActivity.java

В этом упражнении я загружаю фрагмент с RecyclerView.

ListFragment.java

У меня также DialogFragment и ItemAdapter

От адаптера я показывающий DialogFragment

Полный адаптер код

public class TypeAdapter extends RecyclerView.Adapter<CostTypeAdapter.ViewHolder> { 
    private static final String TAG = "TypeAdapter"; 
    private List<CostType> mCostsType; 
    private Context mContext; 

public CostTypeAdapter(Context context, List<CostType> coststype) { 
    mContext = context; 
    mCostsType = coststype; 

} 

@Override 
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { 
    // Create a new view. 
    View v = LayoutInflater.from(viewGroup.getContext()) 
      .inflate(R.layout.costtype_row, viewGroup, false); 

    return new ViewHolder(v); 
} 

// BEGIN_INCLUDE(recyclerViewOnBindViewHolder) 
@Override 
public void onBindViewHolder(final ViewHolder viewHolder, final int position) { 
    //Log.d(TAG, "Element " + position + " set."); 
    String Name = mCostsType.get(position).getName(); 
    viewHolder.tvName.setText(Name); 

    //mView click 
    viewHolder.cardView.setPreventCornerOverlap(false); 
    viewHolder.cardView.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      //Dialog here 
      FragmentActivity activity = (FragmentActivity)(mContext); 
      FragmentManager fm = activity.getSupportFragmentManager(); 

      CostType costType = new CostType(); 
      costType.setTypeID(mCostsType.get(position).getTypeID()); 
      costType.setName(mType.get(position).getName()); 
      costType.setPriority(0); 
      CostsTypeDialogFragment alertDialog = CostsTypeDialogFragment.newInstance(costType); 
      alertDialog.show(fm, "cost_type"); 

     } 
    }); 


} 
// END_INCLUDE(recyclerViewOnCreateViewHolder) 

public void refreshList() { 
    this.notifyDataSetChanged(); 
    System.out.println("refreshList"); 

} 



@Override 
public int getItemCount() { 
    return mType.size(); 
} 

/** 
* Provide a reference to the type of views that you are using (custom ViewHolder) 
*/ 
public static class ViewHolder extends RecyclerView.ViewHolder { 
    private final TextView tvName; 
    private final CardView cardView; 

    public ViewHolder(View v) { 
     super(v); 

     v.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       Log.d(TAG, "Element " + getPosition() + " clicked."); 

      } 
     }); 
     tvName = (TextView) v.findViewById(R.id.tvName); 
     cardView = (CardView) v.findViewById(R.id.card_view); 
    } 

} 



} 

DialogFragment.java У меня есть перехватчик для этого диалога для общения с MainActivity

onDialogCloseListener mListener; 
    // Container Activity must implement this interface 
    public interface onDialogCloseListener { 
     public void onDialogClose(); 
    } 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      mListener = (onDialogCloseListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() + " must implement OnDialogClose listener"); 
     } 
    } 
    private List<MyType> mType; 

    ... 

OnClick из диалога:

mListener.onDialogClose(); 

Этот диалог имеет некоторые кнопки. Например, для изменения/удаления элемента в списке переработчиков. В этом диалоге есть интерфейс onDialogCloseListener. Я использую мою MainActivity.

MainActivity.java

public class MainActivity extends BaseActivity implements DialogFragment.onDialogCloseListener { 

    ... 
    @Override 
    public void onDialogClose() { 

     RecyclerView mRecyclerView; 
     mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView); 

     //not working 
     mRecyclerView.getAdapter().notifyDataSetChanged(); 
    } 

я могу использовать mRecyclerView от деятельности таким образом. Я могу, например, сделать его невидимым. Но notifyDataSetChanged не работает.

Мое решение - создать новый адаптер - новый запрос sql, новый список объектов и снова установить его для RecyclerView. Но это, вероятно, не очень хорошо. Потому что я не могу, например, сохранить положение прокрутки.

Но как установить соединение с адаптером? Я хочу иметь возможность добавлять анимацию, например, для удаления элемента.

Edit:

Запуск

mRecyclerView.getAdapter().notifyItemRemoved(0); 

в onDialogClose прекрасно работает. Список обновлен. Но когда я хочу сделать то же самое с

mRecyclerView.getAdapter().notifyDataSetChanged(); 

или

mRecyclerView.getAdapter().notifyItemChanged(0); 

В списке не освежает.

+0

Вам просто нужно уведомить набор данных, измененный на адаптере? – Onheiron

+0

@ Onheiron это было бы самым простым способом, но я читал, что это не так просто с RecyclerView. Если есть возможность использовать только notifyDataSetChanged, значит да. Но мне нужно иметь возможность получить предмет из адаптера. Например, при удалении показывайте анимацию, сохраняйте положение прокрутки. – adek

+0

Вы могли бы опубликовать полный код адаптера? – Onheiron

ответ

4

Совет 1: не показывать диалог внутри класса адаптера, сделать свой onClick вызвать собственный слушателя внутри Activity например, onItemClicked(CostType costType)

class MyAdapter extends RecyclerView.Adapter .. { 

    public interface OnItemClickListener { 
     void onItemClicked(CostType costType); 
    } 

    private OnItemClickListener mListener; 

    // setter and getter for OnitemClickListener 

    // inside onBindViewHolder 
    viewHolder.cardView.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
     CostType costType = new CostType(); 
     costType.setTypeID(mCostsType.get(position).getTypeID()); 
     costType.setName(mType.get(position).getName()); 
     costType.setPriority(0); 
     mListener.onItemClicked(costType); 
     } 

} 

class MyActivity extends Activity { 

    // inside onCreate 
    adapter.setOnItemClickListener(new ...); 

} 

Совет 2: если вам нужно доставить результат из фрагмента B фрагментировать, вам не нужно использовать активности, вместо этого использовать setTargetFragment/getTargetFragment методы.

// inside MyListFragment 
MyDialogFragment frag = MyDialogFragment.newInstance(); 
frag.setTargetFragment(this, 0); 
// commit transaction 

// inside MyDialogFragment to trigger listener, make sure MyDialogFragment 
// implement OnDialogCloseListener interface 
((MyListFragment)getTargetFragment()).onDialogClose(); 
+0

Спасибо. Вот почему я просил хорошего образца. Поэтому я должен переместить мой onClick в MainActivity (а не на активность фрагмента). Но как это сделать. Точно так же я сделал с прослушивателем DialogFragment? – adek

+1

@adek отредактировал мой ответ, добавил код. –

+0

У вас есть +1 от меня. Но это, вероятно, не устраняет мою проблему с обновлением списка recyclerview. Где я должен добавить notifyDataSetChanged(). В MyActivity он не работает. Вероятно, перемещение этого кода здесь не изменит, но я попробую. – adek