简体   繁体   中英

List adapter null outside onCreateView() - android

I am working with fragments and libraries like slidingMenu, pullToRefreshListViews, and android Aquery. In my app I want to fill up my ListView using a custom adapter with data I parse from JSON.

here's the rough code

public class MyFragment extends Fragment {

public MyFragment() {
    // Empty constructor required for fragment subclasses
}
    //initialize some variables here....
    PullToRefreshListView   list;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
final View rootView = inflater.inflate(//my layout xml, container, false);
aq = new AQuery(getActivity(),rootView);
list = (PullToRefreshListView) rootView.findViewById(R.id.list);
asyncJson(); // this method fetches,parses json and sets adapter to the listview
return rootView;
    }
}

the asyncJson() method is something like this.

public void asyncJson(){
    aq.ajax(url, JSONArray.class, expire, new AjaxCallback<JSONArray>() {

        @Override
        public void callback(String url, JSONArray json, AjaxStatus status) {
    try{
           // fetch and parse json store data in array<List>
        }
      if(adapter == null){
                adapter = new MyAdapter(getView().getContext(),//array<list> variables);
                list.setAdapter(adapter);

                }
                else if(adapter != null){

                    adapter.notifyDataSetChanged();

                }
    }
 });
}

Logcat gives me null pointer exception at list.setAdapter(adapter); this line. I have no syntax errors. Is this because of the context I pass to the adapter I tried just getActivity() but that didn't work either is the list null or the adapter? :0 what am I doing wrong?

Thanks! Logcat Image

app project files: https://www.dropbox.com/s/9sa1l8wm4rnmnew/stackoverflow.zip

It's mostly your Context that's giving you the NullPointerException .

Try passing a Context to your fragment via the constructor and use it in the adapter.

private Context ctx;

  public MyFragment(Context ctx) {
    this.ctx = ctx;
}

And initialize the adapter like this:

adapter = new MyAdapter(ctx, array<list> variables);

I guess you are using this library ...

https://github.com/chrisbanes/Android-PullToRefresh

Dowload it and you need to import the following and add it as dependency on our project.

PullToRefreshListFragment library

I modify the project that I download from the link on your comment. You can download it from here:

https://dl.dropboxusercontent.com/u/33565803/StackOverFlowExamples/chrisbanes%20-%20Android-PullToRefresh-master-plusHeader.zip

I am gonna write the code as well so we dont depends of this link on this answer ;). So we have only one class call MainActivity that extends from FragmentActivity.

public class MainActivity extends FragmentActivity implements PullToRefreshBase.OnRefreshListener<ListView> {

FragmentManager fm = getSupportFragmentManager();
private PullToRefreshListFragment mPullRefreshListFragment;

private PullToRefreshListView mPullRefreshListView;
private ListView mActualListView;

private String[] mStrings = {"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
        "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
        "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre",
        "Allgauer Emmentaler"};

private LinkedList<String> mListItems;
private ArrayAdapter<String> mAdapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // sliding menu implementation
    /*final SlidingMenu menu = new SlidingMenu(this);
    menu.setMode(SlidingMenu.LEFT);
    menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
    menu.setShadowWidthRes(R.dimen.shadow_width);
    menu.setShadowDrawable(R.drawable.shadow);
    menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
    menu.setFadeDegree(0.35f);
    menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
    menu.setMenu(R.layout.menu);*/

    // event handlers come after slidingmenu

    mPullRefreshListFragment = (PullToRefreshListFragment) getSupportFragmentManager().findFragmentById(R.id.frag_ptr_list);

    //aq = new AQuery(getActivity(),mPullToRefreshListFragment.getView());

    /*mPullRefreshListView.setOnScrollListener(new EndlessScrollListener();*/


    mPullRefreshListView = mPullRefreshListFragment.getPullToRefreshListView();

    // Set a listener to be invoked when the list should be refreshed.
    mPullRefreshListView.setOnRefreshListener(this);


    // You can also just use mPullRefreshListFragment.getListView()
    mActualListView = mPullRefreshListView.getRefreshableView();


    mListItems = new LinkedList<String>();
    mListItems.addAll(Arrays.asList(mStrings));
    mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);

    View headerView = getLayoutInflater().inflate(R.layout.list_header, null);
    mActualListView.addHeaderView(headerView);
    mActualListView.setAdapter(mAdapter);

    mPullRefreshListFragment.setListShown(true);
    /*asyncJson(1,expire);*/

}

public void asyncJson(int page, final long expire) {
    // GET JSON FROM THE WEB AND PARSE IT
    // ALSO STORE DATA IN ARRAY LIST VARIABLES

    if (expire == -1) {
        mPullRefreshListView.onRefreshComplete();
    }

    //if(pg == 1 && expire !=-1){

        //If you wanna add a header at this point, do it like this
        View headerView = getLayoutInflater().inflate(R.layout.list_header, null);
        mActualListView.addHeaderView(headerView);
        // DO SOMETHING
    //}

    //Just notify the changes because the adapter do exist
    mAdapter.notifyDataSetChanged();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public void onRefresh(PullToRefreshBase<ListView> refreshView) {
    // Do work to refresh the list here.
    new GetDataTask().execute();
}


private class GetDataTask extends AsyncTask<Void, Void, String[]> {

    @Override
    protected String[] doInBackground(Void... params) {
        // Simulates a background job.
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
        }
        return mStrings;
    }

    @Override
    protected void onPostExecute(String[] result) {
        mListItems.addFirst("Added after refresh...");
        mAdapter.notifyDataSetChanged();

        // Call onRefreshComplete when the list has been refreshed.
        mPullRefreshListView.onRefreshComplete();

        super.onPostExecute(result);
    }
  }
}

This are the layouts we have :

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >


     <fragment
             android:id="@+id/frag_ptr_list"
             android:name="com.handmark.pulltorefresh.extras.listfragment.PullToRefreshListFragment"
             android:layout_width="match_parent"
             android:layout_height="match_parent" />


</RelativeLayout>

list_row.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

<TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

list_header.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#4a2">

<TextView
        android:id="@+id/text"
        android:gravity="center"
        android:text="My Header"
        android:textColor="#fff"
        android:layout_width="match_parent"
        android:layout_height="40dp"/>
</RelativeLayout>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM