Hot questions for Using Butter Knife in adapter
Question:
why RecyclerView adapter not working with ButterKnife ?
It's working with findViewById but not working with ButterKnife
Adapter Class
public class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.viewHolder>{ Context context; List<CategoriesModels> categoriesModels; public CategoriesAdapter(Context context,List<CategoriesModels> categoriesModels){ this.context = context; this.categoriesModels = categoriesModels; } @Override public viewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_categories, viewGroup, false); viewHolder viewHolder = new viewHolder(view); return viewHolder; } @Override public void onBindViewHolder(@NonNull viewHolder viewHolder, int i) { } @Override public int getItemCount() { return categoriesModels.size(); } class viewHolder extends RecyclerView.ViewHolder { @BindView(R.id.img_flag) ImageView img_flag; @BindView(R.id.txt_title) TextView txt_title; @BindView(R.id.img_correct) ImageView img_correct; public viewHolder(View view) { super(view); ButterKnife.bind(context,view); } } }
MainActivity Class
public class CategoriesActivity extends AppCompatActivity { @BindView(R.id.txt_select_language) TextViewFont txt_select_language; @BindView(R.id.rv_categories) RecyclerView rv_categories; List<CategoriesModels> categoriesModels = new ArrayList<>(); CategoriesAdapter categoriesAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_categories); ButterKnife.bind(CategoriesActivity.this); //show data ShowDate(); } private void ShowDate() { Retrofit retrofit = new Retrofit.Builder().baseUrl("http://*****").addConverterFactory(GsonConverterFactory.create()).build(); RetrofitService retrofitService = retrofit.create(RetrofitService.class); Call<List<CategoriesModels>> call = retrofitService.get_categories(); call.enqueue(new Callback<List<CategoriesModels>>() { @Override public void onResponse(Call<List<CategoriesModels>> call, Response<List<CategoriesModels>> response) { List<CategoriesModels> list = response.body(); for (CategoriesModels i : list) { categoriesModels.add(new CategoriesModels(i.getId(), i.getTitle(), i.getPhoto(), i.getShortcut())); } categoriesAdapter = new CategoriesAdapter(CategoriesActivity.this, categoriesModels); rv_categories.setLayoutManager(new LinearLayoutManager(CategoriesActivity.this, LinearLayoutManager.VERTICAL, false)); rv_categories.setAdapter(categoriesAdapter); } @Override public void onFailure(Call<List<CategoriesModels>> call, Throwable t) { } }); } }
I tried a lot before putting up the subject but I did not find a solution yet....................................................................................
Answer:
inside viewHolder constructor replace context to be this
ButterKnife.bind(this,view);
this refer to ViewHolder class which contain view you want to inject!\
Take a look to ButterKnife Examples. https://jakewharton.github.io/butterknife/
Question:
I got an exception null object reference, when i use setAdapter to recyceler view in onCreateView method in Fragment. Please tell me what i do wrong or how i can do this? I use getActivity() instead of "this".
I need create TabbedActivity. Can i do this whithout fragment?
One.java
public class One extends Fragment { @BindView(R.id.recycler_view) RecyclerView recyclerView; @BindView(R.id.button2) Button button; private WebSitesViewModel mWebSitesViewModel; int i = 0; MyRecViewAdapter adapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ButterKnife.bind(getActivity()); String url = getActivity().getIntent().getStringExtra(Intent.EXTRA_TEXT); if (url != null) { if (isNetworkConnected(getActivity())) { One.JsoupAsyncTask jsoupAsyncTask = new One.JsoupAsyncTask(this); jsoupAsyncTask.execute(url); Toast.makeText(getActivity(), R.string.bookmarks_added, Toast.LENGTH_LONG).show(); } else { Toast.makeText(getActivity(), "Network not connected!", Toast.LENGTH_LONG).show(); } } mWebSitesViewModel = ViewModelProviders.of(this).get(WebSitesViewModel.class); adapter = new MyRecViewAdapter(getActivity(), mWebSitesViewModel ); recyclerView.setAdapter(adapter); recyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); mWebSitesViewModel.getAllWebSites().observe(this, new Observer<List<WebSites>>() { @Override public void onChanged(@Nullable final List<WebSites> webSites) { // Update the cached copy of the words in the adapter. adapter.setWebSites(webSites); } }); initSwipe(); return inflater.inflate(R.layout.fragment_container, container, false); } public static boolean isNetworkConnected(Context c) { ConnectivityManager connectivityManager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); return activeNetworkInfo != null && activeNetworkInfo.isConnected(); } private static class JsoupAsyncTask extends AsyncTask<String, Void, Void> { private final WeakReference<One> activityWeakReference; JsoupAsyncTask(One context) { activityWeakReference = new WeakReference<>(context); } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Void doInBackground(String... url) { try { Document document = Jsoup.connect(url[0]).get(); Element img = document.select("img").first(); String imgSrc = img.absUrl("src"); addData(document.title(), url[0], imgSrc); } catch (IOException e ) { e.printStackTrace(); } return null; } private void addData(String head, String url, String imgSrc) { WebSites webSites = new WebSites(head, url, imgSrc, 0); activityWeakReference.get().mWebSitesViewModel.insert(webSites); } } private void initSwipe() { ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | RIGHT) { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return makeMovementFlags(0, RIGHT); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { final int position = viewHolder.getAdapterPosition(); if (direction == RIGHT) { mWebSitesViewModel.delete(adapter.getmWebSites().get(position)); adapter.notifyItemRemoved(position); } } }; ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback); itemTouchHelper.attachToRecyclerView(recyclerView); } }
fragment_container.xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/all" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="dev.zca.mybookmarks.selectfragment.ContainerActivity$PlaceholderFragment"> <TextView android:id="@+id/section_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="aassqs" /> </android.support.constraint.ConstraintLayout>
Exception
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference at dev.zca.mybookmarks.selectfragment.One.onCreateView(One.java:77)
Answer:
You need to bind your views in a different manner when using fragments. Instead of using:
ButterKnife.bind(getActivity());
You need to first inflate your view and then feed it into Butterknife:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_container, container, false); ButterKnife.bind(this, view); ... return view; }
There's an example on the Butterknife homepage under Non-Activity Binding.