Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ package com.cocosw.framework.core; import android.app.ProgressDialog; import android.content.ActivityNotFoundException; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.app.FragmentManager; import android.support.v4.content.Loader; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import com.cocosw.accessory.connectivity.NetworkConnectivity; import com.cocosw.accessory.utils.UIUtils; import com.cocosw.accessory.views.QuickReturn; import com.cocosw.framework.R; import com.cocosw.framework.app.CocoBus; import com.cocosw.framework.app.Injector; import com.cocosw.framework.exception.CocoException; import com.cocosw.framework.exception.ExceptionManager; import com.cocosw.framework.loader.CocoLoader; import com.cocosw.framework.loader.ThrowableLoader; import com.cocosw.framework.uiquery.CocoQuery; import com.cocosw.lifecycle.LifecycleDispatcher; import com.cocosw.undobar.UndoBarController; import com.cocosw.undobar.UndoBarController.UndoListener; import com.squareup.otto.Bus; import java.lang.reflect.Field; import java.util.HashSet; import java.util.Map; import butterknife.ButterKnife; /** * Activity */ public abstract class Base<T> extends ActionBarActivity implements DialogResultListener, CocoLoader<T> { protected CocoQuery q; private ThrowableLoader<T> loader; protected Bus bus = CocoBus.getInstance(); private HashSet<OnActivityInsetsCallback> mInsetCallbacks; private SystemBarTintManager.SystemBarConfig mInsets; private SystemBarTintManager tintManager; RetainedFragment retainedFragment; private QuickReturn qr; private static final String TAG_RETAINED_STATE_FRAGMENT = "_retainedStateFragment"; @Override public void onDialogResult(final int requestCode, final int resultCode, final Bundle arguments) { // Intentionally left blank } @SuppressWarnings("deprecation") @Override protected void onCreate(final Bundle savedInstanceState) { try { super.onCreate(savedInstanceState); } catch (Exception e) { //workround for V7 appcompact } LifecycleDispatcher.get().onActivityCreated(this, savedInstanceState); q = q == null ? new CocoQuery(this) : q; setContentView(layoutId()); tintManager = new SystemBarTintManager(this); ActionBar ab = getSupportActionBar(); if (ab != null) { ab.setDisplayHomeAsUpEnabled(true); } // enable status bar tint tintManager.setStatusBarTintEnabled(true); // enable navigation bar tint tintManager.setNavigationBarTintEnabled(true); if (UIUtils.hasKitKat()) { TypedValue typedValue = new TypedValue(); try { getTheme().resolveAttribute( getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA).theme, typedValue, true); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } int[] attribute = new int[] { R.attr.colorPrimary, R.attr.colorPrimaryDark, R.attr.navigationBarColor, R.attr.statusBarColor }; TypedArray array = this.obtainStyledAttributes(typedValue.resourceId, attribute); int colorPrimary = array.getResourceId(0, R.color.black); int colorPrimaryDark = array.getResourceId(1, -1); int navigationBarColor = array.getResourceId(2, -1); int statusBarColor = array.getResourceId(3, -1); colorPrimaryDark = colorPrimaryDark < 0 ? colorPrimary : colorPrimaryDark; navigationBarColor = navigationBarColor < 0 ? colorPrimaryDark : navigationBarColor; statusBarColor = statusBarColor < 0 ? colorPrimaryDark : statusBarColor; tintManager.setStatusBarTintResource(statusBarColor); tintManager.setNavigationBarTintResource(navigationBarColor); } ButterKnife.inject(this); // use Retained Fragment to handle runtime changes if (hasRetainData()) { FragmentManager fm = getSupportFragmentManager(); retainedFragment = (RetainedFragment) fm.findFragmentByTag(TAG_RETAINED_STATE_FRAGMENT); // create the fragment and data the first time if (retainedFragment == null) { // add the fragment retainedFragment = new RetainedFragment(); fm.beginTransaction().add(retainedFragment, TAG_RETAINED_STATE_FRAGMENT).commit(); } } try { init(savedInstanceState); } catch (final RuntimeException e) { ExceptionManager.error(e, this); return; } catch (final Exception e) { ExceptionManager.error(e, this); finish(); return; } onStartLoading(); getSupportLoaderManager().initLoader(this.hashCode(), getIntent().getExtras(), this); } protected SystemBarTintManager getTintManager() { return tintManager; } protected void inject() { Injector.inject(this); } @Override public Loader<T> onCreateLoader(final int arg0, final Bundle arg) { loader = new ThrowableLoader<T>(this, null) { @Override public T loadData() throws Exception { return pendingData(arg); } }; return loader; } /** * Loading data in background * * @param arg * @return * @throws Exception */ @Override public T pendingData(final Bundle arg) throws Exception { return null; } @Override public void onLoadFinished(final Loader<T> loader, final T items) { final Exception exception = getException(loader); onStopLoading(); if (exception != null) { showError(exception); return; } onLoaderDone(items); } /** * This interface will be triggered after background been loaded * * @param items */ @Override public void onLoaderDone(final T items) { } /** * Show exception * * @param e */ @Override public void showError(final Exception e) { try { ExceptionManager.handle(e, this); } catch (final CocoException e1) { showRefresh(e1); } } protected void showRefresh(final CocoException e) { UndoBarController.show(this, e.getMessage(), new UndoListener() { @Override public void onUndo(final Parcelable token) { refresh(); } }, UndoBarController.RETRYSTYLE); } /** * Get exception from loader if it provides one by being a * {@link ThrowableLoader} * * @param loader * @return exception or null if none provided */ protected Exception getException(final Loader<T> loader) { if (loader instanceof ThrowableLoader) { return ((ThrowableLoader<T>) loader).clearException(); } else { return null; } } @Override public void onLoaderReset(final Loader<T> arg0) { } public abstract int layoutId(); /** * ??? * * @param saveBundle */ protected abstract void init(Bundle saveBundle) throws Exception; private ProgressDialog dialog; /** * Restart current activity */ protected void restart() { Intent intent = getIntent(); overridePendingTransition(0, 0); intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); finish(); overridePendingTransition(0, 0); startActivity(intent); } @Override protected void onDestroy() { super.onDestroy(); LifecycleDispatcher.get().onActivityDestroyed(this); hideLoading(); // hack for null point exception try { final Field INSTANCES_MAP = LayoutInflater.class.getDeclaredField("INSTANCES_MAP"); INSTANCES_MAP.setAccessible(true); ((Map<?, ?>) INSTANCES_MAP.get(null)).remove(this); } catch (final Exception e) { // e.printStackTrace(); } } @Override protected void onStart() { super.onStart(); bus.register(this); supportInvalidateOptionsMenu(); LifecycleDispatcher.get().onActivityStarted(this); } @Override public boolean onOptionsItemSelected(final MenuItem item) { if (item.getItemId() == android.R.id.home) { finish(); return true; } return super.onOptionsItemSelected(item); } @Override public void onResume() { super.onResume(); onInsetsChanged(tintManager.getConfig()); LifecycleDispatcher.get().onActivityResumed(this); } @Override public void onPause() { super.onPause(); LifecycleDispatcher.get().onActivityPaused(this); } protected void refresh() { onStartLoading(); getSupportLoaderManager().restartLoader(0, new Bundle(), this); } protected final <E extends View> E view(int resourceId) { return (E) findViewById(resourceId); } @Override protected void onStop() { super.onStop(); bus.unregister(this); LifecycleDispatcher.get().onActivityStopped(this); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); LifecycleDispatcher.get().onActivitySaveInstanceState(this, outState); } protected void onStartLoading() { } protected void onStopLoading() { hideLoading(); } /** * Check network connection * * @throws CocoException */ protected void checkNetwork() throws CocoException { if (!NetworkConnectivity.getInstance().isConnected()) { throw new CocoException(getString(R.string.network_error)); } } /** * Show loading dialog, not safe for UI thread */ protected void showLoading(final String str) { if (dialog == null) { dialog = new ProgressDialog(this); dialog.setCancelable(false); } dialog.setMessage(str); if (!dialog.isShowing()) { dialog.show(); } } /** * Close loading dialog */ protected void hideLoading() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } private long exitTime; /** * ?onBackPressed * * @return , ture */ protected boolean finishWithConfirm() { if (System.currentTimeMillis() - exitTime > 3000) { showExitConfirm(); exitTime = System.currentTimeMillis(); return false; } else { finish(); return true; } } /** * UI will be shown when confirm activity finishing, call in finishWithConfirm() */ protected void showExitConfirm() { new UndoBarController.UndoBar(this).message(R.string.confirm_opt_exit).duration(3000).show(); } protected void addInsetChangedCallback(OnActivityInsetsCallback callback) { if (mInsetCallbacks == null) { mInsetCallbacks = new HashSet<>(); } mInsetCallbacks.add(callback); if (mInsets != null) { callback.onInsetsChanged(mInsets); } } protected void removeInsetChangedCallback(OnActivityInsetsCallback callback) { if (mInsetCallbacks != null) { mInsetCallbacks.remove(callback); } } protected void onInsetsChanged(SystemBarTintManager.SystemBarConfig insets) { mInsets = insets; if (mInsetCallbacks != null && !mInsetCallbacks.isEmpty()) { for (OnActivityInsetsCallback callback : mInsetCallbacks) { callback.onInsetsChanged(insets); } } } public void setInsetTopAlpha(float alpha) { tintManager.setStatusBarAlpha(alpha); } protected void resetInsets() { setInsetTopAlpha(255); } protected static interface OnActivityInsetsCallback { public void onInsetsChanged(SystemBarTintManager.SystemBarConfig insets); } protected boolean hasRetainData() { return true; } protected void save(String key, Object obj) { if (retainedFragment != null) retainedFragment.put(key, obj); } protected void save(Object obj) { if (retainedFragment != null) retainedFragment.put(obj.getClass().getName(), obj); } protected <T> T load(String key) { if (retainedFragment != null) return (T) retainedFragment.get(key); return null; } public void startActivitySafely(Intent intent) { try { super.startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); } catch (SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); } } public void startActivityForResultSafely(Intent intent, int requestCode) { try { super.startActivityForResult(intent, requestCode); } catch (ActivityNotFoundException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); } catch (SecurityException e) { Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); } } protected Object load(Object obj) { return obj = load(obj.getClass().getName()); } }