Adding load more, in order to fetch more workflows from myexperiment
Project: http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/commit/5569845c Tree: http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/tree/5569845c Diff: http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/diff/5569845c Branch: refs/heads/master Commit: 5569845c5eb7c41b6789f6eda246a75faa38772d Parents: 8371cca Author: larrytech7 <larrya...@gmail.com> Authored: Wed Aug 5 17:29:54 2015 +0100 Committer: larrytech7 <larrya...@gmail.com> Committed: Wed Aug 5 17:29:54 2015 +0100 ---------------------------------------------------------------------- .../mobile/adapters/WorkflowAdapter.java | 46 ++++++++ .../mobile/fragments/FavoriteFragment.java | 1 - .../mobile/fragments/WorkflowItemFragment.java | 118 ++++++++++++++----- .../taverna/mobile/utils/WorkflowLoader.java | 99 +--------------- .../xmlparsers/MyExperimentXmlParserRules.java | 2 +- 5 files changed, 140 insertions(+), 126 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/blob/5569845c/app/src/main/java/org/apache/taverna/mobile/adapters/WorkflowAdapter.java ---------------------------------------------------------------------- diff --git a/app/src/main/java/org/apache/taverna/mobile/adapters/WorkflowAdapter.java b/app/src/main/java/org/apache/taverna/mobile/adapters/WorkflowAdapter.java index 134eae6..74c42ed 100644 --- a/app/src/main/java/org/apache/taverna/mobile/adapters/WorkflowAdapter.java +++ b/app/src/main/java/org/apache/taverna/mobile/adapters/WorkflowAdapter.java @@ -86,6 +86,52 @@ public class WorkflowAdapter extends RecyclerView.Adapter<WorkflowAdapter.ViewHo favDB = new Workflow_DB(context, WORKFLOW_FAVORITE_KEY); } + public void addItems(List<Workflow> workflow, int position) throws ClassCastException{ + //add item to the list +// workflowList.add(position,workflow); + workflowList.addAll(workflow); + notifyItemRangeInserted(position + 24, 25); + } + + public void removeItem(Workflow workflow){ + workflowList.remove(workflow); + //notifyItemRemoved(); + } + + /** + * Register a new observer to listen for data changes. + * <p/> + * <p>The adapter may publish a variety of events describing specific changes. + * Not all adapters may support all change types and some may fall back to a generic + * {@link android.support.v7.widget.RecyclerView.AdapterDataObserver#onChanged() + * "something changed"} event if more specific data is not available.</p> + * <p/> + * <p>Components registering observers with an adapter are responsible for + * {@link #unregisterAdapterDataObserver(android.support.v7.widget.RecyclerView.AdapterDataObserver) + * unregistering} those observers when finished.</p> + * + * @param observer Observer to register + * @see #unregisterAdapterDataObserver(android.support.v7.widget.RecyclerView.AdapterDataObserver) + */ + @Override + public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) { + super.registerAdapterDataObserver(observer); + } + + /** + * Unregister an observer currently listening for data changes. + * <p/> + * <p>The unregistered observer will no longer receive events about changes + * to the adapter.</p> + * + * @param observer Observer to unregister + * @see #registerAdapterDataObserver(android.support.v7.widget.RecyclerView.AdapterDataObserver) + */ + @Override + public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) { + super.unregisterAdapterDataObserver(observer); + } + @Override public WorkflowAdapter.ViewHolder onCreateViewHolder(ViewGroup parentViewGroup, int viewType) { View v = LayoutInflater.from(context).inflate(R.layout.workflow_item_layout,parentViewGroup,false); http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/blob/5569845c/app/src/main/java/org/apache/taverna/mobile/fragments/FavoriteFragment.java ---------------------------------------------------------------------- diff --git a/app/src/main/java/org/apache/taverna/mobile/fragments/FavoriteFragment.java b/app/src/main/java/org/apache/taverna/mobile/fragments/FavoriteFragment.java index f200d32..5eb0930 100644 --- a/app/src/main/java/org/apache/taverna/mobile/fragments/FavoriteFragment.java +++ b/app/src/main/java/org/apache/taverna/mobile/fragments/FavoriteFragment.java @@ -88,7 +88,6 @@ public class FavoriteFragment extends Fragment implements RecyclerView.OnCreateC setUpFavoriteData(); setUpListView(); } - }; setUpFavoriteData(); http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/blob/5569845c/app/src/main/java/org/apache/taverna/mobile/fragments/WorkflowItemFragment.java ---------------------------------------------------------------------- diff --git a/app/src/main/java/org/apache/taverna/mobile/fragments/WorkflowItemFragment.java b/app/src/main/java/org/apache/taverna/mobile/fragments/WorkflowItemFragment.java index 73be405..adcfb60 100644 --- a/app/src/main/java/org/apache/taverna/mobile/fragments/WorkflowItemFragment.java +++ b/app/src/main/java/org/apache/taverna/mobile/fragments/WorkflowItemFragment.java @@ -30,23 +30,16 @@ import android.app.SearchManager; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.util.LruCache; import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -67,12 +60,10 @@ import org.apache.taverna.mobile.tavernamobile.Workflow; import org.apache.taverna.mobile.utils.AvatarLoader; import org.apache.taverna.mobile.utils.WorkflowLoader; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; -import java.util.ArrayList; import java.util.List; /** @@ -82,7 +73,7 @@ import java.util.List; * with a GridView. * <p/> */ -public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, SearchView.OnQueryTextListener { +public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,SearchView.OnQueryTextListener { // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER private static final String ARG_PARAM1 = "param1"; @@ -104,12 +95,23 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout * The Adapter which will be used to populate the ListView/GridView with * Views. */ - private static WorkflowAdapter searchAdpater; + // private static WorkflowAdapter searchAdpater; private static View rootView; public static Context cx; private static boolean STATE_ON = false; private static TextView noDataText; private static LruCache<String, Bitmap> avatarCache; + private LinearLayoutManager mLinearLayoutManager; + private static WorkflowAdapter workflowAdapter; + + //variables for controlling the infinite scroll mechanism + private static int previousTotal = 0; + private int visibleThreshold = 3; + private int firstVisibleItem, visibleItemCount, totalItemCount; + private int currentPage = 1; + private boolean loading = true; + private InfiniteScrollListener scrollListener; + private RecyclerView.AdapterDataObserver workflowObserver; public static WorkflowItemFragment newInstance(String param1, String param2) { WorkflowItemFragment fragment = new WorkflowItemFragment(); @@ -132,16 +134,29 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout super.onCreate(savedInstanceState); setHasOptionsMenu(true); cx = getActivity(); + mLinearLayoutManager = new LinearLayoutManager(cx); + scrollListener = new InfiniteScrollListener(); + workflowObserver= new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + super.onChanged(); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + super.onItemRangeInserted(positionStart, itemCount); + mListView.swapAdapter(workflowAdapter,true); + Toast.makeText(getActivity(), "adding more workflows to listview", Toast.LENGTH_SHORT).show(); + } + }; + workflowAdapter = new WorkflowAdapter(getActivity()); + workflowAdapter.registerAdapterDataObserver(workflowObserver); + if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } in = AnimationUtils.loadAnimation(getActivity(),android.R.anim.slide_in_left); - // List<Workflow> mlist = new ArrayList<Workflow>(); - // mlist.add(new Workflow(getActivity(),"Testing title","Larry","Ok testing",0,"http://127.0.0.1")); - /* mlist.add(new Workflow(getActivity(),"Testing title","Larry","Ok testing",0,"http://127.0.0.1")); -*/ - } @Override @@ -150,18 +165,22 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout noDataText = (TextView) rootView.findViewById(android.R.id.empty); swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh); swipeRefreshLayout.setOnRefreshListener(this); + // Set the adapter mListView = (RecyclerView) rootView.findViewById(android.R.id.list); mListView.setHasFixedSize(true); - mListView.setLayoutManager(new LinearLayoutManager(getActivity())); + mListView.setLayoutManager(mLinearLayoutManager); mListView.setAnimation(in); - mListView.setAdapter(new WorkflowAdapter(getActivity())); + mListView.setAdapter(workflowAdapter); + mListView.setOnScrollListener(scrollListener); + mListView.setItemAnimator(new DefaultItemAnimator()); + final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. up to 4MB for high screen densities and 1.2Mb for low sds final int cacheSize = maxMemory / 8; - avatarCache = new LruCache<String, Bitmap>(cacheSize) { + avatarCache = new LruCache<String, Bitmap>(cacheSize){ @Override - protected int sizeOf(String key, Bitmap bitmap) { + protected int sizeOf(String key, Bitmap bitmap){ // The cache size will be measured in kilobytes return bitmap.getByteCount() / 1024; } @@ -201,7 +220,7 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout public void onResume() { super.onResume(); if(!STATE_ON) { - new WorkflowLoader(getActivity(), swipeRefreshLayout).execute(); + new WorkflowLoader(getActivity(), swipeRefreshLayout).execute(""+currentPage); if (mListView.getAdapter().getItemCount() == 0) { mListView.setVisibility(View.GONE); @@ -244,21 +263,22 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout @Override public boolean onOptionsItemSelected(MenuItem item) { if(item.getTitle().equals("Refresh")){ - new WorkflowLoader(getActivity(),swipeRefreshLayout).execute(); + new WorkflowLoader(getActivity(),swipeRefreshLayout).execute(""+currentPage); return true; } return super.onOptionsItemSelected(item); } @Override - public void onDetach() { + public void onDestroy() { super.onDetach(); + workflowAdapter.unregisterAdapterDataObserver(workflowObserver); } -//handle a request to query for given workflows + //handle a request to query for given workflows private void performSearch(String search){ WorkflowAdapter ladapter = new WorkflowAdapter(getActivity()); - WorkflowAdapter wk = searchAdpater;//workflowAdapter; + WorkflowAdapter wk = workflowAdapter;//workflowAdapter; if(!TextUtils.isEmpty(search)) { if (null != wk) @@ -277,7 +297,7 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout @Override public void onRefresh() { - new WorkflowLoader(getActivity(),swipeRefreshLayout).execute(); + new WorkflowLoader(getActivity(),swipeRefreshLayout).execute(""+currentPage); } /** @@ -302,9 +322,13 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout ((Activity)cx).runOnUiThread(new Runnable() { @Override public void run() { - WorkflowItemFragment.searchAdpater = new WorkflowAdapter(cx,data); - WorkflowItemFragment.mListView.setAdapter(WorkflowItemFragment.searchAdpater); - if(WorkflowItemFragment.searchAdpater.getItemCount() == 0){ + WorkflowItemFragment.workflowAdapter = new WorkflowAdapter(cx,data); + workflowAdapter.addItems(data, previousTotal); + //workflowAdapter.notifyItemRangeInserted(previousTotal+24,25); + //mListView.getAdapter().notifyItemRangeInserted(previousTotal+24, 25); + mListView.swapAdapter(new WorkflowAdapter(cx,data), false); + // loadMoreWorkflows(data); + if(WorkflowItemFragment.workflowAdapter.getItemCount() == 0){ mListView.setVisibility(View.GONE); noDataText.setVisibility(View.VISIBLE); // Toast.makeText(cx, cx.getResources().getString(R.string.err_workflow_conn), Toast.LENGTH_LONG).show(); @@ -386,4 +410,38 @@ public class WorkflowItemFragment extends Fragment implements SwipeRefreshLayout avatarCache.put(row_id_as_key, bitmap); } } + + private class InfiniteScrollListener extends RecyclerView.OnScrollListener{ + /** + * Callback method to be invoked when the RecyclerView has been scrolled. This will be + * called after the scroll has completed. + * <p/> + * This callback will also be called if visible item range changes after a layout + * calculation. In that case, dx and dy will be 0. + * + * @param recyclerView The RecyclerView which scrolled. + * @param dx The amount of horizontal scroll. + * @param dy The amount of vertical scroll. + */ + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + visibleItemCount = mListView.getChildCount(); + totalItemCount = mLinearLayoutManager.getItemCount(); + firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition(); + if(loading){ + if(totalItemCount > previousTotal){ + loading = false; + previousTotal = totalItemCount; + } + } + if(!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem+visibleThreshold)){ + //list has reached end, load more. + Toast.makeText(getActivity(), "Loading more", Toast.LENGTH_SHORT).show(); + new WorkflowLoader(getActivity(),swipeRefreshLayout).execute(""+currentPage++); + System.out.println(currentPage); + loading = true; + } + } + } } http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/blob/5569845c/app/src/main/java/org/apache/taverna/mobile/utils/WorkflowLoader.java ---------------------------------------------------------------------- diff --git a/app/src/main/java/org/apache/taverna/mobile/utils/WorkflowLoader.java b/app/src/main/java/org/apache/taverna/mobile/utils/WorkflowLoader.java index af16b68..2346c75 100644 --- a/app/src/main/java/org/apache/taverna/mobile/utils/WorkflowLoader.java +++ b/app/src/main/java/org/apache/taverna/mobile/utils/WorkflowLoader.java @@ -46,25 +46,16 @@ import java.util.List; /** * Created by Larry Akah on 6/13/15. */ -public class WorkflowLoader extends AsyncTask<Object, Object, Object>{ //WorkflowLoaderMain { +public class WorkflowLoader extends AsyncTask<String, Object, Object>{ //WorkflowLoaderMain { private Context ctx; private List<Workflow> userWorkflows; - public static List<Workflow> loadedWorkflows; private SwipeRefreshLayout refreshLayout; - /* public WorkflowLoader(Context context) { - super(context); - ctx = context; - loadedWorkflows = new ArrayList<Workflow>(); - userWorkflows = new ArrayList<Workflow>(); - }*/ - public WorkflowLoader(Context context, SwipeRefreshLayout sw) { this.ctx = context; this.refreshLayout = sw; this.userWorkflows = new ArrayList<Workflow>(); - loadedWorkflows = new ArrayList<Workflow>(); } @Override @@ -74,63 +65,18 @@ public class WorkflowLoader extends AsyncTask<Object, Object, Object>{ //Workflo } @Override - public List<Workflow> doInBackground(Object[] objects) { + public List<Workflow> doInBackground(String[] pages) { //start a network request to fetch user's workflows - /*try { - //for password protected urls use the user's credentials - //Authenticator.setDefault(new TavernaPlayerAPI.Authenticator("taverna","taverna")); - - URL workflowurl = new URL(new TavernaPlayerAPI(ctx).PLAYER_WORKFLOW_URL); - HttpURLConnection connection = (HttpURLConnection) workflowurl.openConnection(); - String userpass = "icep...@gmail.com" + ":" + "creationfox"; - String basicAuth = "Basic " + Base64.encodeToString(userpass.getBytes(), Base64.DEFAULT); - //new String(Base64.encode(userpass.getBytes(),Base64.DEFAULT)); - connection.setRequestProperty ("Authorization", basicAuth); - connection.setRequestProperty("Accept", "application/json"); - connection.setRequestMethod("GET"); - // connection.setDoInput(true); - // connection.setDoOutput(true); - connection.connect(); //send request - Log.i("RESPONSE Code", ""+connection.getResponseCode()); - Log.i("RESPONSE Messsage", ""+connection.getResponseMessage()); - Log.i("Authorization ", ""+connection.getRequestProperty("Authorization")); - - InputStream dis = connection.getInputStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(dis)); - StringBuffer sb = new StringBuffer(); - String jsonData = ""; - while((jsonData = br.readLine()) != null){ - sb.append(jsonData); - } - dis.close(); - br.close(); - JSONArray jsonWorkflow = new JSONArray(sb.toString()); - for(int i=0; i<jsonWorkflow.length();i++){ - JSONObject js = jsonWorkflow.getJSONObject(i); - Log.i("JSON ", js.toString(2)); - JSONObject authorJson = js.getJSONObject("user"); - String title = js.getString("title"); - String description = js.getString("description"); - String url = js.getString("url"); - long id = js.getLong("id"); - userWorkflows.add(new Workflow(ctx,title,">"+authorJson.getString("name"),description,id,url)); - } - return userWorkflows; - } catch (JSONException | IOException e) { - e.printStackTrace(); - }*/ IRule wkflowRule = new MyExperimentXmlParserRules.WorkflowRule(IRule.Type.ATTRIBUTE, "/workflows/workflow", "resource", "uri","id", "version"); IRule workflowNameRule = new MyExperimentXmlParserRules.WorkflowRule(IRule.Type.CHARACTER, "/workflows/workflow"); WorkflowParser xmlParser = new WorkflowParser(new IRule[]{wkflowRule, workflowNameRule}); try { - URL workflowurl = new URL("http://www.myexperiment.org/workflows.xml"); + URL workflowurl = new URL("http://www.myexperiment.org/workflows.xml?page="+Integer.parseInt((pages[0]))); HttpURLConnection connection = (HttpURLConnection) workflowurl.openConnection(); connection.setRequestMethod("GET"); connection.connect(); //send request - - Log.i("RESPONSE Code", ""+connection.getResponseCode()); - Log.i("RESPONSE Messsage", ""+connection.getResponseMessage()); + Log.i("WorkflowLoader","Loading workflows page = "+pages[0]); InputStream dis = connection.getInputStream(); xmlParser.parse(dis, this.userWorkflows); @@ -145,44 +91,9 @@ public class WorkflowLoader extends AsyncTask<Object, Object, Object>{ //Workflo return this.userWorkflows; } -/* - @Override - public void onCanceled(List<Workflow> data) { - super.onCanceled(data); - } - - @Override - public boolean isStarted() { - return super.isStarted(); - } - - @Override - protected void onStartLoading() { - //if there is data available, deliver it at once - if(userWorkflows != null) - deliverResult(userWorkflows); - else{ - forceLoad(); - } - } - - @Override - public void deliverResult(List<Workflow> data) { - if(isStarted()){ - super.deliverResult(data); - - } - } - - @Override - protected void onStopLoading() { - cancelLoad(); - } -*/ - @Override protected void onPostExecute(Object o) { refreshLayout.setRefreshing(false); -// System.out.println("Workflow Count: "+this.userWorkflows.size()); + System.out.println("Workflow Count: "+this.userWorkflows.size()); } } http://git-wip-us.apache.org/repos/asf/incubator-taverna-mobile/blob/5569845c/app/src/main/java/org/apache/taverna/mobile/utils/xmlparsers/MyExperimentXmlParserRules.java ---------------------------------------------------------------------- diff --git a/app/src/main/java/org/apache/taverna/mobile/utils/xmlparsers/MyExperimentXmlParserRules.java b/app/src/main/java/org/apache/taverna/mobile/utils/xmlparsers/MyExperimentXmlParserRules.java index 6e2b402..f9c19fc 100644 --- a/app/src/main/java/org/apache/taverna/mobile/utils/xmlparsers/MyExperimentXmlParserRules.java +++ b/app/src/main/java/org/apache/taverna/mobile/utils/xmlparsers/MyExperimentXmlParserRules.java @@ -335,7 +335,7 @@ public class MyExperimentXmlParserRules { this.workflow.setWorkflow_title(text); this.workflow.setWorkflow_author(""); wlist.add(this.workflow); - WorkflowLoader.loadedWorkflows.add(this.workflow); + //WorkflowLoader.loadedWorkflows.add(this.workflow); ((List<Workflow>)workflowListObject).add(this.workflow); this.workflow = null; }