Java tutorial
/* * The MIT License (MIT) * Copyright (c) 2014 longkai * The software shall be used for good, not evil. */ package org.catnut.fragment; import android.app.ActionBar; import android.content.Intent; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; import android.os.Handler; import android.provider.BaseColumns; import android.util.Log; import android.view.View; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.Toast; import com.android.volley.RequestQueue; import com.android.volley.Response; import org.catnut.R; import org.catnut.adapter.ConversationAdapter; import org.catnut.api.CommentsAPI; import org.catnut.core.CatnutAPI; import org.catnut.core.CatnutProvider; import org.catnut.core.CatnutRequest; import org.catnut.metadata.Comment; import org.catnut.metadata.Status; import org.catnut.metadata.User; import org.catnut.processor.StatusProcessor; import org.catnut.ui.TweetActivity; import org.catnut.util.CatnutUtils; import org.catnut.util.Constants; import org.json.JSONArray; import org.json.JSONObject; /** * ? * * @author longkai */ public class ConversationFragment extends TimelineFragment { public static final String TAG = ConversationFragment.class.getSimpleName(); private static final String[] PROJECTION = new String[] { "c." + BaseColumns._ID, "c." + Comment.created_at, Comment.columnText, Comment.status, Comment.reply_comment, Comment.uid, User.screen_name, User.avatar_large, User.remark, }; private Handler mHandler = new Handler(); private ConversationAdapter mAdapter; private RequestQueue mRequestQueue; private int mTotal; public static ConversationFragment getFragment() { return new ConversationFragment(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(false); mRequestQueue = mApp.getRequestQueue(); mAdapter = new ConversationAdapter(getActivity()); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // load it! mSwipeRefreshLayout.setRefreshing(true); if (savedInstanceState == null) { String key = getString(R.string.pref_first_run); boolean firstRun = mPreferences.getBoolean(key, true); if (firstRun) { refresh(); mPreferences.edit().putBoolean(key, false).commit(); } else if (mPreferences.getBoolean(getString(R.string.pref_keep_latest), true)) { refresh(); } else { initFromLocal(); } } else { initFromLocal(); } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mListView.setAdapter(mAdapter); } @Override public void onStart() { super.onStart(); ActionBar bar = getActivity().getActionBar(); bar.setIcon(R.drawable.ic_action_conversation); bar.setTitle(getString(R.string.received_reply)); } @Override public void onStop() { super.onStop(); mRequestQueue.cancelAll(TAG); } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Cursor c = (Cursor) mAdapter.getItem(position); String status = c.getString(c.getColumnIndex(Comment.status)); Intent intent = new Intent(getActivity(), TweetActivity.class); intent.putExtra(Constants.JSON, status); startActivity(intent); } @Override protected void refresh() { // ??? if (!isNetworkAvailable()) { Toast.makeText(getActivity(), getString(R.string.network_unavailable), Toast.LENGTH_SHORT).show(); initFromLocal(); return; } // refresh! final int size = getFetchSize(); (new Thread(new Runnable() { @Override public void run() { // ??????(?-)???Orz... String query = CatnutUtils.buildQuery(new String[] { BaseColumns._ID }, null, Comment.TABLE, null, BaseColumns._ID + " desc", size + ", 1" // limit x, y ); Cursor cursor = getActivity().getContentResolver().query(CatnutProvider.parse(Status.MULTIPLE), null, query, null, null); // the cursor never null? final long since_id; if (cursor.moveToNext()) { since_id = cursor.getLong(0); } else { since_id = 0; } cursor.close(); final CatnutAPI api = CommentsAPI.to_me(since_id, 0, getFetchSize(), 0, 0, 0); // refresh... mHandler.post(new Runnable() { @Override public void run() { mRequestQueue.add(new CatnutRequest(getActivity(), api, new StatusProcessor.Comments2MeProcessor(), new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d(TAG, "refresh done..."); mTotal = response.optInt(TOTAL_NUMBER); // ??? JSONArray jsonArray = response.optJSONArray(Comment.MULTIPLE); int newSize = jsonArray.length(); // ... Bundle args = new Bundle(); args.putInt(TAG, newSize); getLoaderManager().restartLoader(0, args, ConversationFragment.this); } }, errorListener)).setTag(TAG); } }); } })).start(); } @Override protected void loadMore(long max_id) { // // ?(??||?) boolean fromCloud = mPreferences.getBoolean(getString(R.string.pref_keep_latest), getResources().getBoolean(R.bool.pref_load_more_from_cloud)); if (fromCloud && isNetworkAvailable()) { // ??ok? loadFromCloud(max_id); } else { // loadFromLocal(); // ? new Thread(updateLocalCount).start(); } } private void initFromLocal() { Bundle args = new Bundle(); args.putInt(TAG, getFetchSize()); getLoaderManager().initLoader(0, args, this); new Thread(updateLocalCount).start(); } private void loadFromLocal() { Bundle args = new Bundle(); args.putInt(TAG, mAdapter.getCount() + getFetchSize()); getLoaderManager().restartLoader(0, args, this); mSwipeRefreshLayout.setRefreshing(true); } private void loadFromCloud(long max_id) { mSwipeRefreshLayout.setRefreshing(true); CatnutAPI api = CommentsAPI.to_me(0, max_id, getFetchSize(), 0, 0, 0); mRequestQueue.add(new CatnutRequest(getActivity(), api, new StatusProcessor.Comments2MeProcessor(), new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { Log.d(TAG, "load more from cloud done..."); mTotal = response.optInt(TOTAL_NUMBER); int newSize = response.optJSONArray(Comment.MULTIPLE).length() + mAdapter.getCount(); Bundle args = new Bundle(); args.putInt(TAG, newSize); getLoaderManager().restartLoader(0, args, ConversationFragment.this); } }, errorListener)).setTag(TAG); } private Runnable updateLocalCount = new Runnable() { @Override public void run() { String query = CatnutUtils.buildQuery(new String[] { "count(0)" }, null, Comment.TABLE, null, null, null); Cursor cursor = getActivity().getContentResolver().query(CatnutProvider.parse(Comment.MULTIPLE), null, query, null, null); if (cursor.moveToNext()) { mTotal = cursor.getInt(0); } cursor.close(); } }; @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { int limit = args.getInt(TAG, getFetchSize()); return CatnutUtils.getCursorLoader(getActivity(), CatnutProvider.parse(Comment.MULTIPLE), PROJECTION, null, null, Comment.TABLE + " as c", "inner join " + User.TABLE + " as u on c.uid=u._id", "c." + BaseColumns._ID + " desc", String.valueOf(limit)); } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor data) { if (mSwipeRefreshLayout.isRefreshing()) { mSwipeRefreshLayout.setRefreshing(false); } mAdapter.swapCursor(data); } @Override public void onLoaderReset(Loader<Cursor> loader) { mAdapter.swapCursor(null); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { super.onScrollStateChanged(view, scrollState); boolean canLoading = SCROLL_STATE_IDLE == scrollState // ??? && mListView.getLastVisiblePosition() == mAdapter.getCount() - 1 // && !mSwipeRefreshLayout.isRefreshing(); // ?? // && mAdapter.getCount() > 0; // ? if (canLoading) { // ??? if (mAdapter.getCount() >= mTotal) { Log.d(TAG, "load all done..."); super.loadAllDone(); } else { Log.d(TAG, "load..."); loadMore(mAdapter.getItemId(mAdapter.getCount() - 1)); } } else { Log.d(TAG, "cannot load more!"); } } @Override public boolean onQueryTextChange(String newText) { return false; } }