2017-04-10 7 views
0

Der Versuch, einen generischen Adapter für den RecyclerView zu erstellen.
bereits erforscht andere Lösungen: RecyclerView generic adapter with DataBinding
Add click listener to Generic RecyclerView Adapter
https://github.com/ravirupareliya/Recyclerview-Generic-Adapter/blob/master/app/src/main/java/com/rrr/genericrecyclerview/adapter/RecyclerAdapter.javaRecyclerView generischer Adapter

jedoch in einem etwas anderen Weise implementieren möchten.
Hier ist, wie mein Adapter wie folgt aussieht:

public abstract class GenericAdapter<T> extends RecyclerView.Adapter<BaseHolder<T>> { 

    private OnRecyclerItemClickListener mListener; 
    private List<T> mItems; 
    private final LayoutInflater mLayoutInflater; 

    public GenericAdapter(Context context) { 
     mLayoutInflater = 
       (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     mItems = Collections.emptyList(); 
    } 

    @Override 
    public BaseHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) { 
     // assume that viewType is a resource id returned by getItemViewType 
     // also other solutions are welcome 
     View view = mLayoutInflater.inflate(viewType, parent, false); 

     // TODO: how to create the view holder ?? 
    } 

    @Override 
    public void onBindViewHolder(BaseHolder<T> holder, int position) { 
     T item = mItems.get(position); 
     holder.onBind(item, mListener); 
    } 

    @Override 
    public int getItemCount() { 
     return mItems != null ? mItems.size() : 0; 
    } 

    public void setItems(List<T> items) { 
     mItems = items; 
     notifyDataSetChanged(); 
    } 

    public void setItemClickListener(OnRecyclerItemClickListener listener) { 
     mListener = listener; 
    } 
} 

Dies ist eine Halterbasis Ansicht von dem ich alle anderen Besitzer erweitern möchten:

public abstract class BaseHolder<T> extends RecyclerView.ViewHolder { 

    public BaseHolder(View itemView) { 
     super(itemView); 
    } 

    public abstract void onBind(T item, OnRecyclerItemClickListener listener); 
} 

Das Problem in onCreateViewHolder Methode.
Wie erstelle ich den Ansichtshalter?
Sollte ich irgendwie abstrakten BaseHolder implementieren oder sollte ich irgendwie die Adapter-Klasse ändern Deklaration erweitert. D. H. Statt BaseHolder hier RecyclerView.Adapter> sollte eine generische Implementierung von BaseHolder sein? Ich habe versucht,> aber es funktioniert nicht

Vielen Dank im Voraus für jeden Ratschlag

+0

meine Lösung für ein ähnliches Problem [hier] (https://stackoverflow.com/a/46492112/6831069) –

Antwort

0

Dies ist, was tat ich in meinem „Generic Adapter“:

Sie passieren die Klasse Ihres Halters, der ist entsprechend der aktuellen Ansicht wie folgt aus:

public class FooHolder extends BaseHolder<Foo> { 
    ... // your code with the constructor matching super goes here 
} 

Dann in Ihrem Adapter Konstruktor Sie einen Parameter wie folgt hinzufügen:

public GenericAdapter(Context context, Class<? extends BaseHolder> holderClass) { 
     ... 
     this.holderClass = holderClass; 
} 

Dann in Ihrem onCreateViewHolder Methode können Sie eine Instanz dieser Klasse wie folgt machen:

@Override 
public BaseHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) { 
     ... 
     viewHolder = (BaseHolder) holderClass.getConstructor(View.class).newInstance(view); 
    } 
+0

Danke für die Antwort. Ich boggle diese Zeile (BaseHolder) holderClass.getConstructor (View.class) .newInstance (view); Das kann 4 Arten von Ausnahmen auslösen –

+0

Dies ist, was Sie in Ihrem Ansatz tun können. Ich verwende diese Leitung in meinem Adapter und nichts geht schief. @LeoDroidcoder –

0

Wenn Sie will einzelne generische Adapter verwenden, die verschiedene-2-Layouts Elemente und verschiedene Modelle für unterschiedliche Bildschirm haben, müssen Sie dies versuchen:

erstellen Java-Klasse Adapter "StoreListAdapter.java"

import android.content.Context; 
import android.support.v7.widget.RecyclerView; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.animation.Animation; 
import android.view.animation.AnimationUtils; 
import android.widget.Filter; 
import android.widget.Filterable; 
import android.widget.TextView; 
import java.util.ArrayList; 
import java.util.Collection; 

/** 
* Created by Deepak Sharma on 31/10/17. 
*/ 
public class StoreListAdapter<T> extends RecyclerView.Adapter<StoreListAdapter.ViewHolder> implements Filterable { 

private Collection<T> mItems; 
    private Context context; 
    private int mLayout; 
    IClickable iClickable; 
    private boolean isAnimationAllowed; 
    private StoreSearchFilter<T> mSearchFilter; 

public StoreListAdapter(Context context) 
    { 
     this.context = context; 
    } 
    public void setData(Collection<T> items, boolean isAnimationAllowed) 
    { 
     mItems = items; 
     this.isAnimationAllowed = isAnimationAllowed; 
    } 

    public void setCallback(int layout, IClickable iClickable) 
    { 
     this.mLayout = layout; 
     this.iClickable = iClickable; 
    } 

@Override 
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 
     View view = LayoutInflater.from(viewGroup.getContext()).inflate(mLayout, viewGroup, false); 
     iClickable.init(view); 

     StoreListAdapter.ViewHolder viewHolder = new StoreListAdapter.ViewHolder(view); 

     view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); 
     int width = view.getMeasuredWidth(); 
     int height = view.getMeasuredHeight(); 
//  viewHolder.itemView.getLayoutParams().width = width; 
     viewHolder.itemView.getLayoutParams().height = height+24; 
     return viewHolder; 
    } 

@Override 
    public void onBindViewHolder(StoreListAdapter.ViewHolder viewHolder, int i) { 
     iClickable.execute(viewHolder, mItems.toArray()[i],viewHolder.getAdapterPosition()); 
     if (isAnimationAllowed) 
      setAnimation(viewHolder.itemView, i); 
    } 

    @Override 
    public int getItemCount() { 
     return mItems.size()>0?mItems.size():0; 
    } 

@Override 
    public Filter getFilter() { 
     if (mSearchFilter == null) 
      mSearchFilter = new StoreSearchFilter<T>((ArrayList<StoreModel>) mItems, new IFilteredList<T>() { 
       @Override 
       public void onListFiltered(ArrayList<T> list) { 

        setData(list, false); 
        notifyDataSetChanged(); 
       } 
      }); 
     return mSearchFilter; 
    } 

public class ViewHolder extends RecyclerView.ViewHolder { 

     private final TextView mTextView; 
     //private CheckBox mCheckBox; 

     ViewHolder(View v) { 
      super(v); 
      mTextView = (TextView)v.findViewById(R.id.list_item); 
     } 
    } 

public interface IClickable<T> { 
     public void init(View view); 
     public void execute(StoreListAdapter.ViewHolder holder, T object, int position); 
    } 

/** 
    * Here is the key method to apply the animation 
    */ 
    private void setAnimation(View viewToAnimate, int position) 
    { 
     // If the bound view wasn't previously displayed on screen, it's animated 
     /*if (position > lastPosition) 
     {*/ 
      Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left); 
      viewToAnimate.startAnimation(animation); 
      //lastPosition = position; 
     /*}*/ 
    } 

} 

ein Geschäft Modell erstellen "StoreModel.java":

import android.os.Parcel; 
import android.os.Parcelable; 
import java.util.ArrayList; 
import java.util.List; 

/** 
* Created by Deepak Sharma on 31/10/17. 
*/ 

public class StoreModel implements Parcelable { 

    private String storeName; 
    private int storeId; 
    private String storeAddress; 
    private String storePhone = "(310)816-2365"; 
    private String storeCity; 
    private int prizesAvailable; 
    private double storeLatitude; 
    private double storeLongitude; 
    private List<Games> gamesList; 

    public StoreModel(int id,String sName, String add, String city, int prizes, double lat, double lon, ArrayList<Games> list) 
    { 
     this.storeId = id; 
     this.storeName  = sName; 
     this.storeAddress = add; 
     this.storeCity  = city; 
     this.prizesAvailable = prizes; 
     this.storeLatitude = lat; 
     this.storeLongitude = lon; 
     this.gamesList = list; 
    } 

    public String getStoreName() { 
     return storeName; 
    } 

    public void setStoreName(String storeName) { 
     this.storeName = storeName; 
    } 

    public String getStoreAddress() { 
     return storeAddress; 
    } 

    public void setStoreAddress(String storeAddress) { 
     this.storeAddress = storeAddress; 
    } 

    public String getStoreCity() { 
     return storeCity; 
    } 

    public void setStoreCity(String storeCity) { 
     this.storeCity = storeCity; 
    } 

    public int getPrizesAvailable() { 
     return prizesAvailable; 
    } 

    public void setPrizesAvailable(int prizesAvailable) { 
     this.prizesAvailable = prizesAvailable; 
    } 

    public double getStoreLatitude() { 
     return storeLatitude; 
    } 

    public void setStoreLatitude(double storeLatitude) { 
     this.storeLatitude = storeLatitude; 
    } 

    public double getStoreLongitude() { 
     return storeLongitude; 
    } 

    public void setStoreLongitude(double storeLongitude) { 
     this.storeLongitude = storeLongitude; 
    } 

    public List<Games> getGamesList() { 
     return gamesList; 
    } 

    public void setGamesList(List<Games> gamesList) { 
     this.gamesList = gamesList; 
    } 

    public String getStorePhone() { 
     return storePhone; 
    } 

    public void setStorePhone(String storePhone) { 
     this.storePhone = storePhone; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == this) 
      return true; //If objects equal, is OK 
     if (obj == null) 
      return false; 
     if (!(obj instanceof StoreModel)) 
      return false; 

     if (obj instanceof StoreModel) { 
      StoreModel store = (StoreModel)obj; 
      return ((storeId == store.storeId) && (storeName.equalsIgnoreCase(store.storeName))); 
//   return (storeId == store.storeId) && y == store.y); 
     } 
     return false; 
    } 

    @Override 
    public int hashCode() { 
     return storeId; 
    } 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(this.storeName); 
     dest.writeString(this.storeAddress); 
     dest.writeString(this.storePhone); 
     dest.writeString(this.storeCity); 
     dest.writeInt(this.prizesAvailable); 
     dest.writeDouble(this.storeLatitude); 
     dest.writeDouble(this.storeLongitude); 
     dest.writeList(this.gamesList); 
    } 

    protected StoreModel(Parcel in) { 
     this.storeName = in.readString(); 
     this.storeAddress = in.readString(); 
     this.storePhone = in.readString(); 
     this.storeCity = in.readString(); 
     this.prizesAvailable = in.readInt(); 
     this.storeLatitude = in.readDouble(); 
     this.storeLongitude = in.readDouble(); 
     this.gamesList = new ArrayList<Games>(); 
     in.readList(this.gamesList, Games.class.getClassLoader()); 
    } 

    public static final Parcelable.Creator<StoreModel> CREATOR = new Parcelable.Creator<StoreModel>() { 
     @Override 
     public StoreModel createFromParcel(Parcel source) { 
      return new StoreModel(source); 
     } 

     @Override 
     public StoreModel[] newArray(int size) { 
      return new StoreModel[size]; 
     } 
    }; 
} 

erstellen "store_item.xml":

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/coordinator_game_layout" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"> 

    <android.support.v7.widget.CardView 
     xmlns:card_view="http://schemas.android.com/apk/res-auto" 
     android:id="@+id/store_item_cardview" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     card_view:cardBackgroundColor="@android:color/transparent" 
     card_view:cardElevation="0dp" 
     android:layout_marginTop="@dimen/dp_five"> 

<TextView 
        android:id="@+id/txtStoreName" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:text="Store Name" 
        android:textSize="18sp" /> 

</android.support.v7.widget.CardView> 

</android.support.design.widget.CoordinatorLayout> 

Jetzt in Sie Aktivität oder Fragment Klasse, diese Methode aufrufen Adapter einstellen:

private void setBottomViewAdapter() { 
     // use this setting to improve performance if you know that changes 
     // in content do not change the layout size of the RecyclerView 
     mRecyclerStore.setHasFixedSize(true); 

     // use a linear layout manager 
     LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity()); 
     mRecyclerStore.setLayoutManager(mLayoutManager); 

     // specify an adapter (see also next example) 
     mStoreList = new ArrayList<>(); 
     mStoreList.add(new StoreModel(1001, "Von's", "9860 National Blvd., Los Angeles", "Culver City", 12, 28.624035, 77.365541, getGamesList(8))); 
     mStoreList.add(new StoreModel(1002, "Jack", "1311 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.622665, 77.364082, getGamesList(6))); 
     mStoreList.add(new StoreModel(1003, "Ian", "1430 S Fairfax Ave., Los Angeles", "Culver City", 8, 28.620899, 77.365258, getGamesList(2))); 
     mStoreList.add(new StoreModel(1004, "Jessica Alberto", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.623890, 77.374136, getGamesList(10))); 
     mStoreList.add(new StoreModel(1005, "Robert", "2545 National Blvd, Los Angeles", "Culver City", 6, 28.631175, 77.375661, getGamesList(4))); 
     mStoreList.add(new StoreModel(1006, "Clark", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.627153, 77.381809, getGamesList(11))); 
     mStoreList.add(new StoreModel(1007, "Jason", "9860 National Blvd., Los Angeles", "Culver City", 12, 28.626569, 77.371963, getGamesList(3))); 
     mStoreList.add(new StoreModel(1008, "Papon", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.623155, 77.371677, getGamesList(2))); 
     mStoreList.add(new StoreModel(1009, "Von's", "2545 National Blvd, Los Angeles", "Culver City", 11, 28.611569, 77.38545, getGamesList(13))); 
     mStoreList.add(new StoreModel(1010, "Robert Downey Jr.", "1430 S Fairfax Ave., Los Angeles", "Culver City", 8, 28.623127, 77.369113, getGamesList(4))); 
     mStoreList.add(new StoreModel(1011, "Ben Affleck", "1335 Wilshire Blvd., Santa Monica", "Mid City", 4, 28.62373, 77.39452, getGamesList(12))); 
     mStoreListAdapter = new StoreListAdapter(getActivity()); 
     boolean isAnimate = false; 
     mStoreListAdapter.setData(mStoreList, isAnimate); 
     mStoreListAdapter.setCallback(R.layout.store_item, new StoreListAdapter.IClickable() { 
      @Override 
      public void init(View view) { 
       // Toast.makeText(getActivity(), "Initialized", Toast.LENGTH_SHORT).show(); 
      } 

      @Override 
      public void execute(StoreListAdapter.ViewHolder viewHolder, Object object, int position) { 
       final StoreModel model = (StoreModel) object; 

       View view = viewHolder.itemView; 
       StoreListAdapter.ViewHolder holder = viewHolder; 

       final CoordinatorLayout fabGameview = (CoordinatorLayout) view; 
       final CardView cardView = (CardView) fabGameview.findViewById(R.id.store_item_cardview); 

       TextView txtStoreName = (TextView) cardView.findViewById(R.id.txtStoreName); 

       cardView.setOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         boolean isAddedToBackStack = true; 
         StoreDetailsAndProductListFragment storeDetailsAndProductListFragment = new StoreDetailsAndProductListFragment(); 
         Bundle bundle = new Bundle(); 
         bundle.putParcelable(ExtrasUtil.STORE, model); 
         storeDetailsAndProductListFragment.setArguments(bundle); 
         showOtherFragment(storeDetailsAndProductListFragment, getActivity().getFragmentManager(), isAddedToBackStack); 
        } 
       }); 
      } 
     }); 
     mRecyclerStore.setAdapter(mStoreListAdapter); 
    } 

eine Schnittstelle:

Erstellen Sie eine benutzerdefinierte Filterbare Klasse "StoreSearchFilter.java":

Import Android.widget.Filter; importieren java.util.ArrayList; importieren java.util.List;

/** * Erstellt von Deepak Sharma am 31.10.17. */

public final class StoreSearchFilter<T> { 

    // private final Pattern pattern; 
    private ArrayList<StoreModel> mList; 
    private IFilteredList<T> callback; 

    public StoreSearchFilter(final String regex) 
    { 
//  pattern = Pattern.compile(regex); 
    } 

    public StoreSearchFilter(ArrayList<StoreModel> list, IFilteredList<T> listener) 
    { 
     this.mList = list; 
     this.callback = listener; 
    } 

    @Override 
    protected Filter.FilterResults performFiltering(CharSequence constraint) { 
     Filter.FilterResults results = new Filter.FilterResults(); 
     if (constraint == null || constraint.length() == 0) { 
      results.values = mList; 
      results.count = mList.size(); 
     } 
     else { 
      // Some search copnstraint has been passed 
      // so let's filter accordingly 
      ArrayList<StoreModel> filteredContacts = new ArrayList<StoreModel>(); 

      if (mList!=null && mList.size()>0) 
      { 
      // We'll go through all the contacts and see 
      // if they contain the supplied string 
      for (StoreModel model : mList) { 
       // TODO Here search for the store name match 
       if (model.getStoreName().toUpperCase().contains(constraint.toString().toUpperCase())) { 
        // if `contains` == true then add it 
        // to our filtered list 
        filteredContacts.add(model); 
       } 
       // TODO Here search for the product name match 
       else { 
        List<Games> gameList = model.getGamesList(); 
        if (gameList!=null && gameList.size()>0) 
        { 
        for (Games game : gameList) { 
         if (game.getProductName().toUpperCase().contains(constraint.toString().toUpperCase())) { 
          filteredContacts.add(model); 
          break; 
         } 
        } 
       } 
       } 
      } 
     } 
      // Finally set the filtered values and size/count 
      results.values = filteredContacts; 
      results.count = filteredContacts.size(); 
     } 

     // Return our FilterResults object 
     return results; 
    } 

    @Override 
    protected void publishResults(CharSequence constraint, Filter.FilterResults results) { 
     callback.onListFiltered((ArrayList<T>) results.values); 
    } 
} 
Verwandte Themen