/AppacitiveQueryAdapterSample

A sample android app to demonstrate a pattern of using AppacitiveQueryAdapter for Listview or Gridview.

Primary LanguageJavaMIT LicenseMIT

AppacitiveQueryAdapter

A sample android app to demonstrate a pattern of using AppacitiveQueryAdapter with ListView or GridView.

This example demonstrates how you can create a AppacitiveObjectQueryAdapter by extending the BaseAdapter to feed a ListView or GridView with appacitive entities like objects, connections, users or devices.

This example app creates an adapter for cricket players which are objects of schema type player.

To know more about schema types on appacitive, check this out.

public class AppacitiveObjectQueryAdapter extends BaseAdapter { 

    private Context mContext;
    private String mType;            //  schema type
    private List<String> mFields;    //  fields to fetch from the server. use this to reduce network payloads
    private long mPageNumber = 1;    //  default
    private long mPageSize = 10;     //  default
    private long mTotalRecords = 0;  //  for now
    final private List<AppacitiveObject> mObjects = new ArrayList<AppacitiveObject>();  //  the data source for this adapter
    private AppacitiveQuery query = null;

    ...

The constructor sets the internal fields of the adapter.

public AppacitiveObjectQueryAdapter(Context context, String type, ListString fields, AppacitiveQuery query) { 
    this.mContext = context; 
    this.mType = type; 
    this.mFields = fields; 
    this.query = query; 
    if (query.pageNumber > 0) 
        this.mPageNumber = query.pageNumber; 
    if (query.pageSize > 0) this.mPageSize = query.pageSize;

    //  Populate the data source
    getCurrentPage(); 
}

And now we have overridden BaseAdapters methods like getItem(int position), getCount(), isEmpty() and getItemId(int position) for them to use the internal array mObjects as the data source.

@Override 
public AppacitiveObject getItem(int i) { return this.mObjects.get(i); }

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

@Override 
public boolean isEmpty() { return getCount() == 0; }

...

Some additional helper methods are provided like clear(), addItem(AppacitiveObject player),

addAll(Collection<AppacitiveObject> playerCollection), removeObject(AppacitiveObject player) etc. to easily manipulate the data recieved from appacitive.

The getCurrentPage() fetches the players from appacitive and notifies the ListView when new data is available by calling the notifyDataSetChanged(). The getNextPage() and getPreviousPage() rely on this method internally.

    public void getCurrentPage() {
        this.query.pageNumber = this.mPageNumber;
        this.query.pageSize = this.mPageSize;
        //  Fetch objects from appacitive as requested by the query.
        AppacitiveObject.findInBackground(this.mType, this.query, this.mFields, new Callback<PagedList<AppacitiveObject>>() {
            @Override
            public void success(PagedList<AppacitiveObject> result) {

                //  Set the totalrecords field of the adapter for paging help
                mTotalRecords = result.pagingInfo.totalRecords;

                //  Clear out the existing objects from adapter and add the new ones.
                mObjects.clear();
                mObjects.addAll(result.results);

                //  Notify listeners there is a fresh list of objects.
                notifyDataSetChanged();

                //  Paging utility toast
                Toast.makeText(getContext(), String.format("Showing page " + mPageNumber + " of " + (int) Math.ceil((double) mTotalRecords / (double) mPageSize) + "."), Toast.LENGTH_LONG).show();
            }
            @Override
            public void failure(PagedList<AppacitiveObject> result, Exception e) 
            {
                Log.e("APPACITIVE", e.getMessage());
            }
        });
    }

And now you can override getView() to return a view of your choice.

In the example, we are returning an imageView with the player's head shot and a textView with the player's name.

@Override
public View getView(int i, View view, ViewGroup viewGroup) {
    LayoutInflater li = LayoutInflater.from(getContext());
    View playerItem = li.inflate(R.layout.player_item, null, false);
    ImageView photoView = (ImageView) playerItem.findViewById(R.id.imageView);
    TextView nameView = (TextView) playerItem.findViewById(R.id.name);

    AppacitiveObject player = getItem(i);
    String playerName = player.getPropertyAsString("name");
    String photoUrl = player.getPropertyAsString("photo_url");

    nameView.setText(playerName);
    Picasso.with(getContext())
        .load(photoUrl)
        .placeholder(R.drawable.placeholder)
        .into(photoView);

    return playerItem;
}

And finally just attach your AppacitiveObjectQueryAdapter to your listView with your desired AppacitiveQuery.

    AppacitiveQuery query = new AppacitiveQuery();
    query.pageNumber = 1;
    query.pageSize = 5;
    query.filter = new PropertyFilter("team").isEqualTo("India");
    List<String> fields = null;
    //  Tell the adapter to fire this query on the 'player' schema type.
    AppacitiveObjectQueryAdapter mAdapter = new AppacitiveObjectQueryAdapter(this, "player", fields, query);
    mListView.setAdapter(mAdapter);

The next and previous button click listeners are programmed to instruct the adapter to fetch the next of previous batch of players respectively.

    mNextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mAdapter.getNextPage();
            }
        });

Screenshot

screenshot

Footnote : This example depends on [appacitive android sdk][2] and the amazing image downloading and caching library [picasso][1] by Square. [2]: https://github.com/appacitive/appacitive-sdk-core [1]: http://square.github.io/picasso/