1

I am using butterknife with retrofit. when I load fragment continiously with network call my fragment crashes with null pointer on views. I have implemented unbind in onDestroyView() in fragment...?

I am not getting error while doing the same thing using findviewbyid. Iam using MVP .

Unbinder unbinder;
@BindView(R.id.swipe_refresh_layout)
SwipeRefreshLayout swipeRefreshLayout;

@BindView(R.id.recycler_view_shop)
RecyclerView recyclerView;

@BindView(R.id.ll_content)
LinearLayout layoutContent;

@BindView(R.id.ll_no_data)
LinearLayout layoutNoData;

@BindView(R.id.tv_category_heading)
TextView categoryHeading;

private HomeActivity activity;
private ProgressDialog progressDialog;
DrListFragmentPresenter presenter;


public DrListFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_dr, container, false);
    // bind view using butter knife
    unbinder = ButterKnife.bind(this, rootView);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.addItemDecoration(new DividerItemDecoration(getFragment().getActivity(),DividerItemDecoration.VERTICAL));

    activity = (HomeActivity) getActivity();

    presenter = new DrListFragmentPresenterImpl(this);
    return rootView;
}

@Override
public Fragment getFragment() {
    return this;
}


@Override
public void setCategoriesDetailsAdapter(CategoryWiseItemListingAdapter adapter) {
    recyclerView.setAdapter(adapter);
}





@Override
public void onDestroyView() {
    super.onDestroyView();

    // unbind the view to free some memory
    unbinder.unbind();
}    

}
Adnan Abdollah Zaki
  • 4,328
  • 6
  • 52
  • 58

2 Answers2

0

Check project gradle

dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
    // add this in your code
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'  
}

Check app gradle

apply plugin: 'com.android.application'
apply plugin: 'android-apt'  // add this 

...
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.jakewharton:butterknife:8.6.0'
    // add this 
    apt 'com.jakewharton:butterknife-compiler:8.6.0
}

And in the version 8.8.1

You can add this in app gradle

apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
...
dependencies {
     compile 'com.jakewharton:butterknife:8.8.1'
     annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

And add this in project gradle

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.jakewharton:butterknife-gradle-plugin:8.8.1'
    }
}

And you can check

https://github.com/JakeWharton/butterknife

https://jakewharton.github.io/butterknife/

KeLiuyue
  • 8,149
  • 4
  • 25
  • 42
  • 1
    It's not necessary to add apt 'com.....' to the gradle file. check [this](https://stackoverflow.com/questions/36925765/butter-knife-return-null-pointer). – FarshidABZ Nov 29 '17 at 07:33
  • Thank you for your answer .But in my code , I add this and worked well .And in the new version ,it will add another . – KeLiuyue Nov 29 '17 at 07:37
  • Yes, probably you are using an old version of the butterknife. – FarshidABZ Nov 29 '17 at 07:41
0

I have the same problem with the following scenario:

  1. open fragment A
  2. open fragment B (quickly, before the data in fragment A appears)
  3. reopen fragment A

When opening fragment A for the first time, retrofit calls the API, before the call is complete, moves to fragment B, then fragment A will be called onDestroyView. In this method butterknife is unbinded. When returning to fragment A, the response process from the API is called, now the component is null because it has been unbinded.

Solution: Canceled the request when moving to fragment B (onDestroyView) using call.cancel()

private Call call;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_dr, container, false);
    // bind view using butter knife
    unbinder = ButterKnife.bind(this, rootView);

    call = downloadService.downloadFileWithDynamicUrlSync(fileUrl);
    call.enqueue(){
        // error occured here
    }
}

@Override
public void onDestroyView() {
    super.onDestroyView();

    // unbind the view to free some memory
    unbinder.unbind();

    // cancel request
    call.cancel();
}    
windupurnomo
  • 1,121
  • 1
  • 11
  • 22