0

I'm having a tough time understanding the documentation for endless adapter

I tried following these quick steps by Commonsware to no avail: How can I use a custom adapter with the cwac-endless adapter?

So, first, you get your custom adapter working correctly on its own. Then, you create your EndlessAdapter subclass (with your implementation of cacheInBackground(), etc.), wrap your custom adapter in an instance of your EndlessAdapter subclass, and put your instance of your EndlessAdapter subclass in your ListView

I have three java classes. My activity, my regular adapter (that works before I tried to integrate endless adapter), and I have a subclassed endless adapter. I'm sure I'm just doing something small that is making this not trigger properly. My app does NOT crash, and it SHOWS my "Loading" view, it just never updates, and seems to load a lot of stuff afterwards because the gui really slows down. I'm probably stuck in some kind of loop. Any ideas?

My main activity:

package com.eghdk.myapp.gui;

import java.util.ArrayList;

import android.annotation.TargetApi;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.NavUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;
import com.eghdk.myapp.R;
import com.eghdk.myapp.adapters.MyAdapter;
import com.eghdk.myapp.adapters.MyEndlessAdapter;
import com.eghdk.myapp.util.AppUtil;

public class MyBlog extends ListActivity {
    String content;
    String Url;
    String title;
    ArrayList<String> titles;
    ArrayList<String> urls;
    ArrayList<String> contents;

    MyAdapter adapter;
    int page = 1;
    int count = 20;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_blog);
        // Show the Up button in the action bar.
        setupActionBar();

        titles = new ArrayList<String>();
        urls = new ArrayList<String>();
        contents = new ArrayList<String>();

        adapter = new MyAdapter(this, titles);

        loadDataFromWeb(page, count);

        }
    }

    /**
     * Set up the {@link android.app.ActionBar}, if the API is available.
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setupActionBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getActionBar().setDisplayHomeAsUpEnabled(true);
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            // This ID represents the Home or Up button. In the case of this
            // activity, the Up button is shown. Use NavUtils to allow users
            // to navigate up one level in the application structure. For
            // more details, see the Navigation pattern on Android Design:
            //
            // http://developer.android.com/design/patterns/navigation.html#up-vs-back
            //
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void loadDataFromWeb(int page, int count) {
//I'm using Koushs Ion library to do Async Json calls.
        Ion.with(
                MyBlog.this,
                "http://myblog.com/api/get_posts/?page=" + page + "&count="
                        + count).asJsonObject()
                .setCallback(new FutureCallback<JsonObject>() {
                    @Override
                    public void onCompleted(Exception e, JsonObject result) {

                        String status = result.getAsJsonPrimitive("status")
                                .getAsString();

                        if (!status.equals("ok")) {
                            Log.e("TAG", "api doesn't exist");
                            Log.e("TAG", "api doesn't");

                        } 

                        JsonArray jsonPostArray = result
                                .getAsJsonArray("posts");

                        for (JsonElement jsonElementPost : jsonPostArray) {

                            JsonObject jsonPost = jsonElementPost
                                    .getAsJsonObject();
                            int ID = jsonPost.get("id").getAsInt();
                            title = jsonPost.get("title").getAsString();
                            titles.add(title);
                            content = jsonPost.get("content").getAsString();
                            contents.add(content);


                                at = jsonPost.getAsJsonArray("attachments")
                                        .get(0).getAsJsonObject();
                                Url = at.get("url").getAsString();
                                urls.add(Url);

                        }

                        // Log.d("TAG", ID + "");
                        done();
                    }
                });

    }

    private void done() {
        MyEndlessAdapter endless = new MyEndlessAdapter(adapter, this);
        setListAdapter(endless);
    }

}

MyAdapter.java:

package com.eghdk.myapp.adapters;

import java.util.ArrayList;

import android.R;
import android.content.Context;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MyAdapter extends BaseAdapter {
    ArrayList<String> titles;
    Context context;
    LayoutInflater mInflater;

    public MyAdapter(Context context, ArrayList<String> list) {
        titles = list;
        this.context = context;
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return titles.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        if (convertView == null) {
            convertView = mInflater.inflate(
                    android.R.layout.simple_list_item_1, parent, false);
        }
        ((TextView) convertView.findViewById(R.id.text1)).setText(Html
                .fromHtml(titles.get(position)));
        return convertView;
    }

}

EndlessAdapter:

package com.eghdk.myapp.adapters;

import java.util.ArrayList;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.TextView;

import com.commonsware.cwac.endless.EndlessAdapter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.koushikdutta.async.future.FutureCallback;
import com.koushikdutta.ion.Ion;

public class MyEndlessAdapter extends EndlessAdapter { ArrayList tempList = new ArrayList(); protected String title; protected ArrayList titles; protected String content; protected String atUrl; ArrayAdapter oldadapter; int page = 1, count = 20; Context context;

public MyEndlessAdapter(ListAdapter wrapped, Context ctx) {
    super(wrapped);
    context = ctx;
    titles = new ArrayList<String>();
    oldadapter = (ArrayAdapter) wrapped;

    // TODO Auto-generated constructor stub
}

@Override
protected void appendCachedData() {
    // TODO Auto-generated method stub
    oldadapter.addAll(titles);

}

    @Override
    protected View getPendingView(ViewGroup parent) {
        // TODO Auto-generated method stub
        TextView view = new TextView(context);
        view.setText("LOADING");
        return view;
    }

    @Override
    protected boolean cacheInBackground() throws Exception {
        Ion.with(
                context,
                "http://myblog.com/api/get_posts/?page=" + page + "&count="
                        + count).asJsonObject()
                .setCallback(new FutureCallback<JsonObject>() {
                    @Override
                    public void onCompleted(Exception e, JsonObject result) {
                        if (result == null) {
                            Log.e("TAG", "server crash");
                            Log.e("TAG", " crash");
                        }

                        String status = result.getAsJsonPrimitive("status")
                                .getAsString();

                        if (!status.equals("ok")) {
                            Log.e("TAG", "api doesn't exist");
                            Log.e("TAG", "api doesn't");

                        } else {

                        }

                        JsonArray jsonPostArray = result
                                .getAsJsonArray("posts");
                        int i = 0;
                        for (JsonElement jsonElementPost : jsonPostArray) {
                            Log.d("", i + "");
                            i++;
                            JsonObject jsonPost = jsonElementPost
                                    .getAsJsonObject();
                            int ID = jsonPost.get("id").getAsInt();
                            String url = jsonPost.get("url").getAsString();
                            title = jsonPost.get("title").getAsString();
                            titles.add(title);
                            content = jsonPost.get("content").getAsString();

                            String date = jsonPost.get("date").getAsString();

                            try {
                                JsonObject cat = jsonPost
                                        .getAsJsonArray("categories").get(0)
                                        .getAsJsonObject();
                                String catTitle = cat.get("title")
                                        .getAsString();
                            } catch (Exception e2) {
                                // TODO Auto-generated catch block
                                e2.printStackTrace();
                            }

                            JsonObject author = jsonPost
                                    .getAsJsonObject("author");
                            String name = author.get("name").getAsString();
                            JsonObject at = null;
                            try {
                                at = jsonPost.getAsJsonArray("attachments")
                                        .get(0).getAsJsonObject();
                                atUrl = at.get("url").getAsString();
                                String atMime = at.get("mime_type")
                                        .getAsString();

                            } catch (Exception e1) {
                                // TODO Auto-generated catch block
                                e1.printStackTrace();
                                atUrl = "";

                            }

                        }

                        // Log.d("TAG", ID + "");
                        // done();
                    }
                });
        return true;
    }

}
Community
  • 1
  • 1
EGHDK
  • 17,818
  • 45
  • 129
  • 204

1 Answers1

0

I'm sure I'm just doing something small that is making this not trigger properly.

Let's review the major headings of the "Usage" section of the documentation:

  • Constructors: you are calling the constructor on your EndlessAdapter subclass

  • Placeholder: you have implemented getPendingView() on your EndlessAdapter subclass

  • The Loading: you have implemented cacheInBackground() on your EndlessAdapter subclass, and while your implementation is strange (three ArrayList<String> rather than one ArrayList<WhateverYourActualModelObjectShouldBe>?), it probably works

  • The Attaching: BZZZT -- your appendCachedData() does not do anything

  • The Threading: your code should be fine, so long as you are not trying to use other AsyncTasks at the same time, or if your android:targetSdkVersion is under 13

  • The Overriding: your code should be fine

So, I would recommend that you go back to The Attaching, read through that section, and peek at the demo app's implementation. Yours may be more complicated, as you chose to use BaseAdapter rather than ArrayAdapter, despite your data model being an array.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I'm going to change my array to an ArrayAdapter. And... what is this problem with multiple async tasks? I am trying to support 10 & up. – EGHDK Jan 19 '14 at 13:39
  • @EGHDK: I would recommend that you go back to and re-read [The Threading](https://github.com/commonsguy/cwac-endless#the-threading), in particular clicking on [the link to the blog post that covers this issue](http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html), and then perhaps look up `AsyncTask` in an Android development book that I think you have. :-) – CommonsWare Jan 19 '14 at 13:41
  • When I pass the ArrayAdapter into EndlessAdapter, how do I go about apending my new ArrayList to the adapter? – EGHDK Jan 19 '14 at 13:56
  • EDIT: Lost here: " take the data cached by cacheInBackground() and append it to the ListAdapter you used in the constructor" – EGHDK Jan 19 '14 at 14:02
  • @EGHDK: Well, if it were an `ArrayAdapter`, you would use methods on `ArrayAdapter` like `add()`. – CommonsWare Jan 19 '14 at 14:12
  • I updated myEndlessAdapter. I'm trying to cast the "wrapped" ListAdapter as an ArrayAdapter, but it won't compile. – EGHDK Jan 19 '14 at 14:19
  • @EGHDK: "it won't compile" is an incomplete description of your symptoms; expecting somebody to be able to help you based upon just saying that is unrealistic. At this point, I would recommend putting your project aside for a while. As you hopefully noticed at the top of the CWAC-Endless `README`, I have been planning on rebooting the endless-adapter stuff. That is because `EndlessAdapter` is not really well-suited for newcomers to Android. I will strive to implement an `EndlessArrayAdapter` in the next few days as part of this reboot, which should be easier for you to integrate. – CommonsWare Jan 19 '14 at 14:24
  • I did notice that. I think I'm going to try to work on this all day today and see where I get. I'll reply back if I seem to get a breakthrough. – EGHDK Jan 19 '14 at 14:36
  • Okay, so I seem to be getting somewhere. My endless adapter isn't crashing anymore. Now it is my MyAdapter. Cast exception. Can't cast from arraylist to string at getView `((TextView) convertView.findViewById(android.R.id.text1)).setText(Html .fromHtml(titles.get(position)));` – EGHDK Jan 19 '14 at 14:48
  • I scratched my whole project, and just tried using your demo and it works! I'm able to get my post_title to display and retrieve data correctly. Though you demo seems to leave out the middle man adapter. So I only have a listActivity and myEndlessAdapter. Should what would be the easiest way to put in another adapter to serve as the middle man. I need something that can override getView so I can customize my list items. – EGHDK Jan 20 '14 at 03:13
  • @EGHDKL: "Though you demo seems to leave out the middle man adapter" -- no, it does not. All versions of `DemoAdapter` (my `EndlessAdapter` subclass) wrap an `ArrayAdapter` in their constructors. – CommonsWare Jan 20 '14 at 12:45