0

I have successfully created a demo for EndlessList from this tutorial. Now As I wanted to use this EndlessList in my project with live web data, I have modified the demo code like below,

MainActivity.java

public class MainActivity extends Activity implements EndlessListView.EndlessListener,OnDismissListener
{
    EndlessListView lv;
    int mult = 1; 
    List<String> data;

    private ProgressDialog pd; 

    static final String KEY_ITEM = "item";
    static final String KEY_TITLE = "title";
    static final String KEY_DESCRIPTION = "description";
    static final String KEY_LINK = "link";
    static final String KEY_AUTHOR = "author";
    static final String KEY_GUID = "guid";

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

    @Override 
    public void onStart() 
    {
        super.onStart(); 
        lv = (EndlessListView) findViewById( R.id.listView );
    }

    @Override 
    public void onResume()
    {
        super.onResume();
        EndlessAdapter adp = new EndlessAdapter ( this, getXMLList(), R.layout.row_layout );
        lv.setAdapter(adp);
        lv.setListener(this);
        pd = new ProgressDialog(this);
        pd.setTitle( "Loading" );
        pd.setMessage( "Please wait" );
        pd.setIndeterminate(true);
        pd.setCancelable(false);
        pd.setOnDismissListener(this);
    }

    private class FakeLoader extends AsyncTask<String, Void, List<String> >
    {
        @Override 
        protected void onPreExecute() 
        {
            if ( pd != null )
            {
                pd.show();
            }
        }

        @Override 
        protected List<String> doInBackground ( String...params )
        {
            return getXMLList();
        }

        @Override 
        protected void onPostExecute ( List<String> result )
        {
            if ( pd != null ) 
            {
                pd.dismiss();
            }
            data = result;
        }
    }

    private List<String> getXMLList()
    {
        try
        {
            XMLParser parser = new XMLParser();
            String xml = parser.getXMLFromUrl( "http://www.vogella.com/article.rss" );
            Document doc = parser.getDomElement(xml);

            NodeList nl = doc.getElementsByTagName( KEY_ITEM );

            data = new ArrayList<String>();

            for ( int i = 0 ; i < nl.getLength() ; i++ )
            {
                Element el = (Element) nl.item( i );
                data.add( parser.getValue( el, KEY_LINK ) );
            }
        }
        catch ( Exception e ) { System.out.println ( "Error : " + e.toString() ); }

        return data;
    }

    @Override
    public void loadData() 
    {
        mult += 10; 
        FakeLoader fl = new FakeLoader(); 
        fl.execute(new String[]{});
    }

    @Override
    public void onDismiss(DialogInterface arg0) 
    {
        lv.addNewData(data);
    }
}

EndlessAdapter.java

public class EndlessAdapter extends ArrayAdapter<String> 
{
    private List<String> itemList;
    private Context context; 
    private int layoutId;

    public EndlessAdapter ( Context context, List<String> itemList, int layoutId )
    {
        super ( context, layoutId,itemList );
        this.itemList = itemList; 
        this.context = context;
        this.layoutId = layoutId;
    }

    @Override 
    public int getCount() 
    {
        return itemList.size();
    }

    @Override
    public String getItem ( int position )
    {
        return itemList.get(position);
    }

    @Override
    public long getItemId ( int position )
    {
        return itemList.get(position).hashCode();
    }

    @Override 
    public View getView ( int position, View convertView, ViewGroup parent )
    {
        View result = convertView;

        if ( result == null )
        {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
            result = inflater.inflate( layoutId, parent, false );
        }

        TextView txtView = (TextView) result.findViewById( R.id.txtItem );
        txtView.setText( itemList.get(position) );

        return result;
    }
}

EndlessListView.java

public class EndlessListView extends ListView implements OnScrollListener 
{
    private boolean isLoading; 
    private EndlessListener listener; 
    private EndlessAdapter adapter;


    public EndlessListView ( Context context, AttributeSet attrs, int defStyle )
    {
        super( context, attrs, defStyle );
        this.setOnScrollListener(this);
    }

    public EndlessListView ( Context context, AttributeSet attrs )
    {
        super ( context, attrs ); 
        this.setOnScrollListener(this);
    }

    public EndlessListView ( Context context )
    {
        super ( context ); 
        this.setOnScrollListener(this);
    }

    public void setListener ( EndlessListener listener )
    {
        this.listener = listener;
    }

    @Override 
    public void onScroll( AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount )
    {
        if ( getAdapter() == null )
        {
            return; 
        }

        if ( getAdapter().getCount() == 0 )
        {
            return; 
        }

//      int l = visibleItemCount + firstVisibleItem;
//      
//      if ( l >= totalItemCount && !isLoading )
//      {
//          isLoading = true;
//          listener.loadData();
//      }

        boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount; 

        if ( loadMore && !isLoading )
        {
            isLoading = true;
            listener.loadData();
        }
    }

    @Override 
    public void onScrollStateChanged ( AbsListView view, int scrollState ) {} 

    public void setAdapter ( EndlessAdapter adapter )
    {
        super.setAdapter(adapter);
        this.adapter = adapter; 
    }


    public void addNewData ( List<String> data )
    {
        isLoading = false;
        adapter.addAll(data);
        adapter.notifyDataSetChanged();
    }

    public EndlessListener setListener() 
    { 
        return listener;
    }

    public static interface EndlessListener
    {
        public void loadData(); 
    }
}

But when I run above code, it shows me NullPointerException at line: 29 in EndlessAdapter.java, The at line 29 is, return itemList.size(); of getCount() method.

Following is error log :

02-05 14:22:37.734: E/AndroidRuntime(15402): FATAL EXCEPTION: main
02-05 14:22:37.734: E/AndroidRuntime(15402): java.lang.RuntimeException: Unable to resume activity {com.example.endlesslistdemo/com.example.endlesslistdemo.MainActivity}: java.lang.NullPointerException
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2602)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2630)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2116)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.access$600(ActivityThread.java:134)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1251)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.os.Looper.loop(Looper.java:137)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.main(ActivityThread.java:4666)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at java.lang.reflect.Method.invokeNative(Native Method)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at java.lang.reflect.Method.invoke(Method.java:511)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:809)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:576)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at dalvik.system.NativeStart.main(Native Method)
02-05 14:22:37.734: E/AndroidRuntime(15402): Caused by: java.lang.NullPointerException
02-05 14:22:37.734: E/AndroidRuntime(15402):    at com.example.endlesslistdemo.EndlessAdapter.getCount(EndlessAdapter.java:29)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.widget.ListView.setAdapter(ListView.java:464)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at com.example.endlesslistdemo.EndlessListView.setAdapter(EndlessListView.java:76)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at com.example.endlesslistdemo.MainActivity.onResume(MainActivity.java:51)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1159)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.Activity.performResume(Activity.java:4584)
02-05 14:22:37.734: E/AndroidRuntime(15402):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2588)
02-05 14:22:37.734: E/AndroidRuntime(15402):    ... 12 more

I have already give INTERNET permission in AndroidManifest.xml file.

Edit:

Following is my code of XMLParser

public String getXMLFromUrl ( String url )
{
    String xml = "";

    try
    {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost ( url );
        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        xml = EntityUtils.toString(entity);
    }
    catch ( Exception e )
    {
        e.printStackTrace();
    }

    return xml;
}

Here at this line HttpPost httpPost = new HttpPost ( url ); It is giving me NPE.

user3264399
  • 284
  • 1
  • 13
  • error is on line number 29 of EndlessAdapter. – Digvesh Patel Feb 05 '14 at 09:00
  • @DigveshPatel, Yes logs says same thing. Please read the question. – user3264399 Feb 05 '14 at 09:01
  • you should not call getXMList() on the UI Thread since is performing network operations. By the way, getXMList is returning null, so one of the operations you perform before creating the data ArrayList is throwing an exception – Blackbelt Feb 05 '14 at 09:06
  • @blackbelt You are correct, `String xml = parser.getXMLFromUrl( "http://www.vogella.com/article.rss" );` here xml is null. How can I solve this ? – user3264399 Feb 05 '14 at 09:14

3 Answers3

0
private List<String> getXMLList()
{
    data = new ArrayList<String>();

    try
    {
        XMLParser parser = new XMLParser();
        String xml = parser.getXMLFromUrl( "http://www.vogella.com/article.rss" );
        Document doc = parser.getDomElement(xml);

        NodeList nl = doc.getElementsByTagName( KEY_ITEM );

        for ( int i = 0 ; i < nl.getLength() ; i++ )
        {
            Element el = (Element) nl.item( i );
            data.add( parser.getValue( el, KEY_LINK ) );
        }
    }
    catch ( Exception e ) { System.out.println ( "Error : " + e.toString() ); }

    return data;
}

If you modify the gemXMLList method to never return null, you get the NPE fixed, however user doesn't see error. You could consider adding functionality to display the error in that case.

public String getXMLFromUrl(String url) {
    String xml = "";

    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        xml = EntityUtils.toString(entity);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return xml;
}

Based your comment url might be null here because it's throwing NPE in line HttpPost httpPost = new HttpPost(url);

Niko
  • 8,093
  • 5
  • 49
  • 85
0

Ok, I Solve the problem my self, the problem was due to NetworkOnMainThreadException. I added the following code in OnCreate() method and it is working fine now.

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
user3264399
  • 284
  • 1
  • 13
  • You should NEVER run network request on main thread, thats why the policy has been set in the first place. Use Thread or AsyncTask for network requests. – Niko Feb 05 '14 at 09:44
  • @Niko, Ok, I will update my code accordingly. Thanks for your help :) – user3264399 Feb 05 '14 at 09:45
  • Please don't continue asking in the same thread, since the original problem is solved. – Niko Feb 05 '14 at 09:45
-1

The method private List<String> getXMLList() returns null if it fails. Change it to:

  private List<String> getXMLList()
  {
      data = new ArrayList<String>();

      try
      {
          XMLParser parser = new XMLParser();
          String xml = parser.getXMLFromUrl( "http://www.vogella.com/article.rss" );
          Document doc = parser.getDomElement(xml);

          NodeList nl = doc.getElementsByTagName( KEY_ITEM );

          for ( int i = 0 ; i < nl.getLength() ; i++ )
          {
              Element el = (Element) nl.item( i );
              data.add( parser.getValue( el, KEY_LINK ) );
          }
      }
      catch ( Exception e ) { System.out.println ( "Error : " + e.toString() ); }

      return data;
  }
Manitoba
  • 8,522
  • 11
  • 60
  • 122