Skip to content

Add RecyclerView sample #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Update ListView sample to utilize ParseQueryPager
  • Loading branch information
grantland committed Feb 5, 2016
commit c66fed4888cde1f08977c36aabfe56528db73f5d
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
package com.parse.ui.widget.sample;

import android.database.DataSetObserver;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseQueryAdapter;
import com.parse.widget.util.ParseQueryPager;

import java.util.List;

import bolts.CancellationTokenSource;

public class ListActivity extends AppCompatActivity {

private static final String TAG = "ListActivity";
public class ListActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
Expand All @@ -26,32 +32,205 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

ListView listView = (ListView) findViewById(R.id.list);

ParseQueryAdapter<ParseObject> adapter = new ParseQueryAdapter<>(this,
new ParseQueryAdapter.QueryFactory<ParseObject>() {
@Override
public ParseQuery<ParseObject> create() {
return ParseQuery.getQuery("Contact")
.orderByAscending("name")
.setCachePolicy(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
MyAdapter<ParseObject> adapter = new MyAdapter<>(createPager());
listView.setAdapter(adapter);
}

private ParseQueryPager<ParseObject> createPager() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("TestObject");
query.orderByAscending("name");
query.setCachePolicy(ParseQuery.CachePolicy.CACHE_THEN_NETWORK);
return new ParseQueryPager<>(query, 25);
}

public static class MyAdapter<T extends ParseObject> extends BaseAdapter {

public static final int TYPE_ITEM = 0;
public static final int TYPE_NEXT = 1;

private static class ItemViewHolder extends ViewHolder {
TextView textView;

public ItemViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}

private static class NextViewHolder extends ViewHolder {
TextView textView;
ProgressBar progressBar;

public NextViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(android.R.id.text1);
progressBar = (ProgressBar) itemView.findViewById(android.R.id.progress);
}

public void setLoading(boolean loading) {
if (loading) {
textView.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.VISIBLE);
progressBar.setIndeterminate(true);
} else {
textView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.INVISIBLE);
progressBar.setIndeterminate(false);
}
}
}

private final Object lock = new Object();
private ParseQueryPager<T> pager;
private CancellationTokenSource cts;

public MyAdapter(ParseQueryPager<T> pager) {
swap(pager);
}

public ParseQueryPager<T> getPager() {
synchronized (lock) {
return pager;
}
}

public void swap(ParseQueryPager<T> pager) {
synchronized (lock) {
if (cts != null) {
cts.cancel();
}
this.pager = pager;
this.cts = new CancellationTokenSource();
}
}

private void loadNextPage() {
final ParseQueryPager<T> pager;
final CancellationTokenSource cts;

synchronized (lock) {
pager = this.pager;
cts = this.cts;
}

// Utilizing callbacks to support CACHE_THEN_NETWORK
pager.loadNextPage(new FindCallback<T>() {
@Override
public void done(List<T> results, ParseException e) {
if (results == null && e == null) { // cancelled
return;
}

if (e != null) {
notifyDataSetChanged();
return;
}
}, android.R.layout.simple_list_item_1);
adapter.setTextKey("name");
adapter.addOnQueryLoadListener(new ParseQueryAdapter.OnQueryLoadListener<ParseObject>() {
@Override
public void onLoading() {
Log.d(TAG, "loading");
}

@Override
public void onLoaded(List<ParseObject> objects, Exception e) {
Log.d(TAG, "loaded");
if (e != null
&& e instanceof ParseException
&& ((ParseException) e).getCode() != ParseException.CACHE_MISS) {
Toast.makeText(ListActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();

notifyDataSetChanged();
}
}, cts.getToken());
notifyDataSetChanged();
}

@Override
public int getCount() {
ParseQueryPager<T> pager = getPager();
return pager.getObjects().size() + (pager.hasNextPage() ? 1 : 0);
}

@Override
public T getItem(int position) {
List<T> objects = getPager().getObjects();
return position < objects.size() ? objects.get(position) : null;
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public final View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view;
if (convertView == null) {
holder = onCreateViewHolder(parent, getItemViewType(position));
view = holder.itemView;
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
});
listView.setAdapter(adapter);
onBindViewHolder(holder, position);
return view;
}

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case TYPE_ITEM: {
View v = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new ItemViewHolder(v);
}
case TYPE_NEXT: {
View v = inflater.inflate(R.layout.load_more_list_item, parent, false);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!getPager().isLoadingNextPage()) {
loadNextPage();
}
}
});
NextViewHolder vh = new NextViewHolder(v);
vh.textView.setText(R.string.load_more);
return vh;
}
default:
throw new IllegalStateException("Invalid view type: " + viewType);
}
}

public void onBindViewHolder(ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case TYPE_ITEM: {
ParseObject item = getItem(position);

ItemViewHolder vh = (ItemViewHolder) holder;
vh.textView.setText(item.getString("name"));
}
break;
case TYPE_NEXT: {
NextViewHolder vh = (NextViewHolder) holder;
vh.setLoading(getPager().isLoadingNextPage());
}
break;
}
}

@Override
public int getViewTypeCount() {
return 2;
}

@Override
public int getItemViewType(int position) {
return position < getPager().getObjects().size() ? TYPE_ITEM : TYPE_NEXT;
}

@Override
public void registerDataSetObserver(DataSetObserver observer) {
super.registerDataSetObserver(observer);
// We use this method as a notification that the ListView is bound to the adapter.
loadNextPage();
}

public static class ViewHolder {
private View itemView;

public ViewHolder(View itemView) {
this.itemView = itemView;
}
}
}
}
19 changes: 19 additions & 0 deletions ParseUI-Widget-Sample/src/main/res/layout/load_more_list_item.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall" >
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:layout_gravity="center_vertical" />
<ProgressBar
android:id="@android:id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
2 changes: 2 additions & 0 deletions ParseUI-Widget-Sample/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<resources>
<string name="app_name">ParseUI-Widget Sample</string>
<string name="list_name">ListView Sample</string>

<string name="load_more">Load more…</string>
</resources>