Java tutorial
package com.jbirdvegas.mgerrit; /* * Copyright (C) 2013 Android Open Kang Project (AOKP) * Author: Evan Conway (P4R4N01D), 2013 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.app.NavUtils; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; import android.util.Pair; import android.view.Menu; import android.view.MenuItem; import android.widget.ShareActionProvider; import android.widget.Toast; import com.jbirdvegas.mgerrit.adapters.PatchSetAdapter; import com.jbirdvegas.mgerrit.database.SelectedChange; import com.jbirdvegas.mgerrit.database.UserChanges; import com.jbirdvegas.mgerrit.helpers.Tools; import com.jbirdvegas.mgerrit.message.NewChangeSelected; import com.jbirdvegas.mgerrit.message.SearchQueryChanged; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import de.greenrobot.event.EventBus; import hugo.weaving.DebugLog; /** * An activity representing a single Change detail screen. This * activity is only used on handset devices. On tablet-size devices, * change details are presented side-by-side with a list of changes * <p> * This activity is mostly just a 'shell' activity containing nothing * more than a {@link com.jbirdvegas.mgerrit.PatchSetViewerFragment}. */ public class PatchSetViewerActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> { private ShareActionProvider mShareActionProvider; private PatchSetAdapter mAdapter; private ViewPager mViewPager; private EventBus mEventBus; // Relevant details for the selected change private String mStatus; private String mChangeId; private Integer mChangeNumber; private Integer mCurrentTab; private Cursor mCursor; private static Integer sChangeIdIndex; private Integer sChangeNumberIndex; @Override protected void onCreate(Bundle savedInstanceState) { this.setTheme(Prefs.getCurrentThemeID(this)); super.onCreate(savedInstanceState); setContentView(R.layout.patchset_pager); // Show the Up button in the action bar. getActionBar().setDisplayHomeAsUpEnabled(true); mEventBus = EventBus.getDefault(); Bundle args = getIntent().getExtras(); mStatus = args.getString(PatchSetViewerFragment.STATUS); setSelectedStatus(mStatus); // Don't pass args here as it does not have search query information getSupportLoaderManager().initLoader(20, null, this); mAdapter = new PatchSetAdapter(this, getSupportFragmentManager(), args); // Set up the ViewPager with the sections adapter. /** The {@link android.support.v4.view.ViewPager} that will host the section contents. */ mViewPager = (ViewPager) findViewById(R.id.tabs); mViewPager.setAdapter(mAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { onNewChangeSelected(position); } }); } private void onNewChangeSelected(int position) { Pair<String, Integer> change = getChangeAtPosition(position); SelectedChange.setSelectedChange(this, change.first, change.second, mStatus); setTitleWithCommit(change.second); mEventBus.postSticky(new NewChangeSelected(change.first, change.second, mStatus, false)); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.change_details_menu, menu); MenuItem item = menu.findItem(R.id.menu_details_share); mShareActionProvider = (ShareActionProvider) item.getActionProvider(); if (mStatus != null) setShareIntent(mChangeId, mChangeNumber); return true; } /** * Constructs a share intent with the change information and sets it to the share * action provider. * @param changeid The ID of the selected change * @param changeNumber The legacy number of the selected change */ private void setShareIntent(String changeid, Integer changeNumber) { if (mShareActionProvider != null) { Intent intent = Tools.createShareIntent(this, changeid, changeNumber); mShareActionProvider.setShareIntent(intent); } } @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.navigateUpTo(this, new Intent(this, GerritControllerActivity.class)); return true; case R.id.menu_details_browser: if (mChangeNumber == null) return false; String webAddress = Tools.getWebAddress(this, mChangeNumber); if (webAddress != null) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress)); startActivity(browserIntent); } else { Toast.makeText(this, R.string.failed_to_find_url, Toast.LENGTH_SHORT).show(); } return true; } return super.onOptionsItemSelected(item); } /** * Sets the details for the selected change and re-creates the options menu. * By using the status, we can query the database and get both the change id * and the change number. * @param status The status of the selected change */ public void setSelectedStatus(String status) { mStatus = status; Pair<String, Integer> change = SelectedChange.getSelectedChange(this, mStatus); mChangeId = change.first; mChangeNumber = change.second; // We need to re-create the options menu to set the share intent again invalidateOptionsMenu(); } @Override public Loader<Cursor> onCreateLoader(int id, @Nullable Bundle args) { if (args == null) { SearchQueryChanged ev = mEventBus.getStickyEvent(SearchQueryChanged.class); if (ev != null) { String to = ev.getClazzName(); if (GerritControllerActivity.class.getSimpleName().equals(to)) args = ev.getBundle(); } } if (args != null) { String databaseQuery = args.getString(SearchQueryChanged.KEY_WHERE); if (databaseQuery != null && !databaseQuery.isEmpty()) { if (args.getStringArrayList(SearchQueryChanged.KEY_BINDARGS) != null) { /* Create a copy as the findCommits function can modify the contents of bindArgs * and we want each receiver to use the bindArgs from the original broadcast */ ArrayList<String> bindArgs = new ArrayList<>(); bindArgs.addAll(args.getStringArrayList(SearchQueryChanged.KEY_BINDARGS)); return UserChanges.findCommits(this, mStatus, databaseQuery, bindArgs); } } } return UserChanges.findCommits(this, mStatus, null, null); } @Override public void onLoaderReset(Loader<Cursor> loader) { sChangeIdIndex = null; sChangeNumberIndex = null; mAdapter.notifyDataSetChanged(); } @Override public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) { /* Weird behaviour: This method gets called multiple times. Once after * initialising this activity and starting the loader, then again later without * manually resetting the loaders. If the current tab is set we have been here, * so we don't need to find the page again. * * Note: We could respond to the database being updated here (this is the only * logical reason explaining the above), but this is called too frequently, * so we will only update this when the user opens the activity */ int pos = 0; mCursor = cursor; sChangeIdIndex = cursor.getColumnIndex(UserChanges.C_CHANGE_ID); sChangeNumberIndex = cursor.getColumnIndex(UserChanges.C_COMMIT_NUMBER); while (cursor.moveToNext()) { if (cursor.getString(sChangeIdIndex).equals(mChangeId)) { pos = cursor.getPosition(); break; } } mAdapter.notifyDataSetChanged(); if (pos == mViewPager.getCurrentItem()) mCurrentTab = pos; else if (mCurrentTab == null) { mCurrentTab = pos; if (mCurrentTab >= 0) mViewPager.setCurrentItem(mCurrentTab); onNewChangeSelected(mCurrentTab); } } @DebugLog public Pair<String, Integer> getChangeAtPosition(int position) { mCursor.moveToPosition(position); return new Pair<>(mCursor.getString(sChangeIdIndex), mCursor.getInt(sChangeNumberIndex)); } public int getNumberOfChanges() { if (mCursor == null || mCursor.isClosed()) return 0; return mCursor.getCount(); } private void setTitleWithCommit(int commitNumber) { String s = getResources().getString(R.string.change_detail_heading); setTitle(String.format(s, commitNumber)); } // Listen for processed search query changes public void onEventMainThread(SearchQueryChanged ev) { getSupportLoaderManager().restartLoader(0, null, this); } }