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.