package com.elphin.framework.app.fpstack;
import android.app.ActivityManager;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.text.TextUtils;
import android.util.Log;
import android.view.Window;
import com.baidu.BaiduMap.R;
import com.elphin.framework.app.ActivityLifecycleCallbacks;
import de.greenrobot.event.EventBus;
import java.util.ArrayList;
import java.util.Stack;
/**
* Task的基类实现,以FragmentActivity作为载体,子页面用Fragment实现
* </p>
*
* @version 1.0
* @author elphinkuo
* @date 13-5-26 下午3:53
*/
public abstract class BaseTask extends FragmentActivity implements Task {
private static final boolean DEBUG = false;
private static final String TAG = BaseTask.class.getSimpleName();
private String taskTag;
protected ActivityLifecycleCallbacks activityLifecycleCallbacks;
protected ReorderStack<Page> pageStack = new ReorderStack<Page>();
private static final String TASKMGR_STATE_KEY = "maps.taskmgr.state";
private static final String TASK_STATE_KEY = "maps.task.state";
private static final String TASK_SIG_KEY = "maps.task.sig";
static final String FRAGMENTS_TAG = "android:support:fragments";
//是否调用了onDestroy API17 新增了 isDestroyed()
boolean mDestroyed = false;
@Override
public TaskManager getTaskManager() {
return TaskManagerFactory.getTaskManager();
}
@Override
public void setTaskTag(String taskTag) {
this.taskTag = taskTag;
}
@Override
public final String getTaskTag() {
return this.taskTag;
}
@Override
public Stack<Page> getPageStack() {
return pageStack;
}
@Override
public void navigateTo(String pageClsName, String pageTagString, Bundle pageArgs) {
if(DEBUG)
Log.d(TAG,"=== navigateTo === "+pageClsName);
if(mDestroyed)
return;
// show
BasePage page = PageFactoryImpl.getInstance().getBasePageInstance(pageClsName,pageTagString);
if(page == null)
return;
//ADD PERFROM LOG
String pageLogTag = page.getPageLogTag();
if(!TextUtils.isEmpty(pageLogTag)) {
PerformanceMonitor.getInstance().addStartTime(pageLogTag,System.currentTimeMillis());
}
page.setTask(this);
if(pageTagString!=null)
page.setPageTag(pageTagString);
BasePage top = null;
if(!pageStack.isEmpty()) {
top = (BasePage) pageStack.peek();
// 如果顶层页面和要跳转到的页面相同
if(top.equals(page)){
try{
getSupportFragmentManager().executePendingTransactions();
}catch (IllegalStateException e) {
if(DEBUG)
e.printStackTrace();
}
Fragment f = getSupportFragmentManager().findFragmentByTag(page.getClass().getName()+page.getPageTag());
if(f != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.remove(page);
ft.commitAllowingStateLoss();
try{
getSupportFragmentManager().popBackStackImmediate();
}catch(Exception e){
if(DEBUG)
e.printStackTrace();
}
page.mIsBack = false;
page.mBackArgs = null;
try{
page.setArguments(pageArgs);
FragmentTransaction ftr = getSupportFragmentManager().beginTransaction();
ftr.add(R.id.fragment_container,page,page.getClass().getName()+page.getPageTag());
ftr.commitAllowingStateLoss();
//add the page to page-stack
//if the record has been in stack,bring it to front
recordPageNavigation(page);
}catch(Exception e){
if(DEBUG)
e.printStackTrace();
}
}
return;
}
}
try{
page.setArguments(pageArgs);
}catch (Exception e) {
}
//add the page to page-stack
//if the record has been in stack,bring it to front
recordPageNavigation(page);
if(DEBUG) {
Log.i(TAG,getTaskManager().dump());
}
navigateAction(top, page,getTaskManager().getStackStrategy());
}
@Override
public void onShowDefaultContent(Intent intent) {
if(DEBUG)
Log.d(TAG,"onShowDefaultContent");
}
/**
* 返回
* @param args 附加参数
* @return 需要外层TaskManager处理返回 false,不需要返回 true
*/
@Override
public boolean goBack(Bundle args) {
if(mDestroyed)
return false;
HistoryRecord record = getTaskManager().getLatestRecord();
if(record == null)
return false;
if(record.taskName.equals(this.getClass().getName())) {
getTaskManager().pop();
if(DEBUG) {
Log.i(TAG,getTaskManager().dump());
}
if(record.pageName == null && pageStack.isEmpty()) {
finish();
return false;
} else {
if(pageStack.isEmpty()) {
HistoryRecord nextRecord = getTaskManager().getLatestRecord();
if(nextRecord!=null) {
navigateTo(nextRecord.pageName,nextRecord.pageSignature,args);
return true;
}else {
finish();
return false;
}
} else {
Page topPage = pageStack.peek();
pageStack.pop();
if(pageStack.isEmpty()) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if(pageStack.isEmpty()) {
ft.remove((BasePage)topPage);
ft.commitAllowingStateLoss();
PageFactoryImpl.getInstance().removePage((BasePage)topPage);
//如果还有历史,则到上个历史页面,否则finish该task
HistoryRecord nextRecord = getTaskManager().getLatestRecord();
if(nextRecord!=null) {
navigateTo(nextRecord.pageName,nextRecord.pageSignature,args);
return true;
}else
finish();
return false;
}
}else
return navigateBackAction((BasePage)topPage,getTaskManager().getStackStrategy(),args);
}
}
}else {
// throw new IllegalStateException("Illegal Page Stack State!");
//如果栈状态错误,结束该Task
finish();
}
return false;
}
@Override
public boolean goBack() {
return goBack(null);
}
private Bundle getArguments() {
Intent localIntent = getIntent();
if(localIntent == null)
return null;
else {
return localIntent.getBundleExtra(TaskManager.NAVIGATE_PAGE_PARAM);
}
}
@Override
public boolean handleBack(Bundle args) {
return false;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
boolean isCalled = false;
int index = requestCode >> 16;
if (index != 0) {
--index;
Bundle bundle = new Bundle();
String key = "index";
bundle.putInt(key,index);
Fragment frag = null;
try{
frag = this.getSupportFragmentManager().getFragment(bundle,key);
}catch(IllegalStateException e){
if(DEBUG)
e.printStackTrace();
}
if (frag == null) {
//没有找到发起调用的fragment,说明不是在fragment内部调用的startActivityForResult
//顶层的fragment没有收到onActivityResult,这里主动再调一次
isCalled=false;
}
else {
//super里面已经调用过,不用再调
isCalled=true;
}
}else{
//index为0,也说明不是在fragment内部调用的startActivityForResult,需要主动再调
isCalled=false;
}
if(!isCalled){
if(!pageStack.isEmpty()) {
Page topPage = pageStack.peek();
if(topPage!=null){
try{
//主动调用
((Fragment)topPage).onActivityResult(requestCode, resultCode, data);
}catch (ClassCastException e){
//Page都是从Fragment继承的,理论上不会到这里,如果以后又重构,可能要修改这里
e.printStackTrace();
}
}
}
}
}
@Override
public void finish() {
if(DEBUG)
Log.d(TAG,"Finish:"+this);
//清理page
Stack<Page> pages = getPageStack();
if(pages!=null && !pages.isEmpty()) {
pages.clear();
}
removeHistoryRecords();
if(DEBUG)
Log.d(TAG,"removeHistoryRecords end\n"+getTaskManager().dump());
super.finish();
}
/**
* 清理该Task中的记录
*/
private boolean removeHistoryRecords() {
if(DEBUG)
Log.d(TAG,"removeHistoryRecords");
ReorderStack<HistoryRecord> historyRecords = TaskManagerFactory.getTaskManager().getHistoryRecords();
ArrayList<HistoryRecord> delItems = new ArrayList<HistoryRecord>();
if(historyRecords!=null) {
for( HistoryRecord record : historyRecords) {
if(record == null || record.taskName.equals(this.getClass().getName())
&& record.taskSignature.equals(HistoryRecord.genSignature(this))) {
delItems.add(record);
}
}
return historyRecords.removeAll(delItems);
}
return false;
}
protected void create(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(activityLifecycleCallbacks == null)
activityLifecycleCallbacks = (ActivityLifecycleCallbacks)getApplication();
if(savedInstanceState!=null) {
if(savedInstanceState.getParcelable(TASKMGR_STATE_KEY)!=null) {
getTaskManager().restoreState(savedInstanceState.getParcelable(TASKMGR_STATE_KEY));
String newSig = HistoryRecord.genSignature(this);
String oldSig = savedInstanceState.getString(TASK_SIG_KEY);
if(!TextUtils.isEmpty(oldSig)) {
((TaskManagerImpl)getTaskManager()).updateHistoryRecord(this.getClass().getName(),
oldSig,newSig);
}
//其实恢复历史记录没有用处
((TaskManagerImpl)getTaskManager()).clearHistoryRecords();
}
notifyTaskChange();
activityLifecycleCallbacks.onActivityCreated(this,savedInstanceState);
return;
}
activityLifecycleCallbacks.onActivityCreated(this,savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
if(activityLifecycleCallbacks == null)
activityLifecycleCallbacks = (ActivityLifecycleCallbacks)getApplication();
if(savedInstanceState!=null) {
if(savedInstanceState.getParcelable(TASKMGR_STATE_KEY)!=null) {
getTaskManager().restoreState(savedInstanceState.getParcelable(TASKMGR_STATE_KEY));
String newSig = HistoryRecord.genSignature(this);
String oldSig = savedInstanceState.getString(TASK_SIG_KEY);
if(!TextUtils.isEmpty(oldSig)) {
((TaskManagerImpl)getTaskManager()).updateHistoryRecord(this.getClass().getName(),
oldSig,newSig);
}
//其实恢复历史记录没有用处,还要清空
((TaskManagerImpl)getTaskManager()).clearHistoryRecords();
if(DEBUG)
android.util.Log.e(TAG,"Activity restore:"+savedInstanceState.toString());
}
notifyTaskChange();
activityLifecycleCallbacks.onActivityCreated(this,savedInstanceState);
if(getTaskManager().getRootRecord()!=null
&& !this.getClass().getName().equals(getTaskManager().getRootRecord().taskName))
finish();
return;
}
notifyTaskChange();
// 处理需要跳转到子页面
Intent localIntent = getIntent();
if(localIntent != null) {
// args
Bundle pageArgs = getArguments();
// navigate page
//if(TaskManager.ACTION_NAVIGATE_PAGE.equals(localIntent.getAction()))
{
String pageName = localIntent.getStringExtra(TaskManager.NAVIGATE_PAGE_NAME);
String pageTag = localIntent.getStringExtra(TaskManager.NAVIGATE_PAGE_TAG);
//no page,show default content ,the param is intent
if(pageName == null || TextUtils.isEmpty(pageName)) {
onShowDefaultContent(localIntent);
if(!isTaskNaviBack(localIntent))
recordTaskNavigation();
// activityLifecycleCallbacks.onActivityCreated(this,savedInstanceState);
}else {
// navigate to page
this.navigateTo(pageName,pageTag,pageArgs);
}
}
}
activityLifecycleCallbacks.onActivityCreated(this,savedInstanceState);
}
private boolean isTaskNaviBack(Intent intent) {
return intent!=null && intent.getBooleanExtra(TaskManager.ACTION_NAVIGATE_BACK, false);
}
private void notifyTaskChange() {
TaskChangeEvent event = new TaskChangeEvent();
event.type = TaskChangeEvent.CHANGE_CUR_TASK;
event.curTask = this;
EventBus.getDefault().post(event);
}
protected void newIntent(Intent intent) {
if(DEBUG)
android.util.Log.e(TAG,"onNewIntent");
super.onNewIntent(intent);
this.setIntent(intent);
}
@Override
protected void onNewIntent(Intent intent) {
if(DEBUG)
android.util.Log.e(TAG,this+"onNewIntent");
super.onNewIntent(intent);
this.setIntent(intent);
// 处理需要跳转到子页面
if(intent != null) {
String pageName = intent.getStringExtra(TaskManager.NAVIGATE_PAGE_NAME);
String pageTag = intent.getStringExtra(TaskManager.NAVIGATE_PAGE_TAG);
if(pageName!=null && !TextUtils.isEmpty(pageName)) {
Bundle pageArgs = getArguments();
this.navigateTo(pageName,pageTag,pageArgs);
} else if(intent.getBooleanExtra(TaskManager.ACTION_NAVIGATE_BACK,false)) {
handleBack(getArguments());
}else {
this.onShowDefaultContent(intent);
if(!isTaskNaviBack(intent))
recordTaskNavigation();
}
}
}
private void recordTaskNavigation() {
HistoryRecord record = new HistoryRecord(this.getClass().getName(), null);
record.taskSignature = HistoryRecord.genSignature(this);
getTaskManager().track(record);
if(DEBUG) {
Log.d(TAG,"recordTaskNavigation");
Log.d(TAG,getTaskManager().dump());
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mDestroyed = true;
activityLifecycleCallbacks.onActivityDestroyed(this);
TaskChangeEvent event = new TaskChangeEvent();
event.type = TaskChangeEvent.REMOVE_TASK;
event.curTask = this;
EventBus.getDefault().post(event);
}
@Override
protected void onResume() {
super.onResume();
activityLifecycleCallbacks.onActivityResumed(this);
notifyTaskChange();
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
checkPageState();
}
private void checkPageState() {
HistoryRecord lastRecord = getTaskManager().getLatestRecord();
if(lastRecord!=null && lastRecord.pageName!=null){
final Stack<Page> pages = getPageStack();
if(pages.isEmpty()) {
navigateTo(lastRecord.pageName,lastRecord.pageSignature,null);
return;
}
}
}
@Override
protected void onPause() {
super.onPause();
activityLifecycleCallbacks.onActivityPaused(this);
}
@Override
protected void onStart() {
super.onStart();
activityLifecycleCallbacks.onActivityStarted(this);
}
@Override
protected void onStop() {
super.onStop();
activityLifecycleCallbacks.onActivityStopped(this);
}
/**
* 系统默认会恢复Fragment状态,在此忽略系统的恢复
* @param outState
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable(TASKMGR_STATE_KEY,getTaskManager().saveState());
outState.putString(TASK_SIG_KEY,HistoryRecord.genSignature(this));
activityLifecycleCallbacks.onActivitySaveInstanceState(this,outState);
if(DEBUG)
android.util.Log.e(TAG,"onSaveInstanceState:"+outState.toString());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if(DEBUG)
Log.d(TAG,"onAttachedToWindow");
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
if(DEBUG)
Log.d(TAG,"onDetachedFromWindow");
}
@Override
public void onBackPressed() {
if(DEBUG)
Log.d(TAG,"onBackPressed");
backAction();
}
private void backAction() {
HistoryRecord record = getTaskManager().getLatestRecord();
if(record == null) {
finish();
return;
}
Bundle backArgs = null;
Page topPage = null;
if(record.taskName.equals(this.getClass().getName())) {
if(!pageStack.isEmpty()) {
topPage = pageStack.peek();
if(topPage.onBackPressed())
return;
}
}
//for QA monkey test
if(CstmConfig.isMonkeyTest(this) && Build.VERSION.SDK_INT >= 8) {
final boolean isMonkeyTest = ActivityManager.isUserAMonkey();
if(isMonkeyTest) {
final Stack<HistoryRecord> records = getTaskManager().getHistoryRecords();
HistoryRecord rootRecord = getTaskManager().getRootRecord();
if(rootRecord != null && records!=null
&& records.size() == 1 && records.peek().equals(rootRecord)) {
return;
}
}
}
//monkey test end
if(topPage!=null)
backArgs = topPage.getBackwardArguments();
if(!goBack(backArgs)){
getTaskManager().onGoBack();
}else{
}
}
/**
* 切换fragment
* @param page
* @param strategy
*/
private void navigateAction(BasePage topPage, BasePage page,int strategy) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
page.mIsBack = false;
switch (strategy) {
// case TaskManager.STACK_STRATEGY_ADD:
// ft.hide((BasePage)pageStack.peek());
// ft.add(R.id.fragment_container,page,page.getClass().getName());
// break;
case TaskManager.STACK_STRATEGY_REPLACE:
if (GlobalConfig.getInstance().isAnimationEnabled()) {
// 添加到栈顶的界面的进入动画
int[] customAnims = page.getCustomAnimations();
int inAnim = customAnims[0];
// 替换掉的界面的退出动画
int outAnim = customAnims[1];
if (topPage != null && !topPage.shouldOverrideCustomAnimations())
outAnim = topPage.getCustomAnimations()[3];
ft.setCustomAnimations(inAnim, outAnim);
}
ft.replace(R.id.fragment_container,page,page.getClass().getName()+page.getPageTag());
break;
default:
{
//throw new IllegalArgumentException("Wrong stack strategy param!");
break;
}
}
ft.commitAllowingStateLoss();
}
/**
* 返回处理
* @param page
* @param strategy
*/
private boolean navigateBackAction(BasePage page, int strategy,Bundle args) {
if(DEBUG)
Log.d(TAG,"navigateBackAction "+page.getClass().getSimpleName());
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if(pageStack.isEmpty()) {
ft.remove(page);
ft.commitAllowingStateLoss();
PageFactoryImpl.getInstance().removePage(page);
finish();
if(DEBUG)
Log.d(TAG,"The Task's page-stack is empty.Finish!");
return false;
}
switch (strategy) {
// case TaskManager.STACK_STRATEGY_ADD:
// ft.remove(page);
// ft.show((BasePage)pageStack.peek());
// break;
case TaskManager.STACK_STRATEGY_REPLACE:
HistoryRecord record = getTaskManager().getLatestRecord();
if(record == null)
return false;
String pageName = record.pageName;
String pageTag = record.pageSignature;
BasePage targetPage = PageFactoryImpl.getInstance().getBasePageInstance(pageName,pageTag);
if(targetPage == null)
return false;
targetPage.mIsBack = true;
targetPage.mBackArgs = args;
//targetPage.setArguments(args);
if (GlobalConfig.getInstance().isAnimationEnabled()) {
// 当前界面的退出动画
int[] customAnims = page.getCustomAnimations();
int outAnim = customAnims[3];
// 回退到的界面的重新进入动画
int inAnim = targetPage.shouldOverrideCustomAnimations() ? customAnims[2]
: targetPage.getCustomAnimations()[0];
ft.setCustomAnimations(inAnim, outAnim);
}
ft.replace(R.id.fragment_container,targetPage,targetPage.getClass().getName()+targetPage.getPageTag());
PageFactoryImpl.getInstance().removePage(page);
break;
default:
break;
//throw new IllegalArgumentException("Wrong stack strategy param!");
}
ft.commitAllowingStateLoss();
return true;
}
private void recordPageNavigation(Page page) {
HistoryRecord record = new HistoryRecord(this.getClass().getName(),page.getClass().getName());
record.taskSignature = HistoryRecord.genSignature(this);
record.pageSignature = page.getPageTag() != null? page.getPageTag():PageFactory.DEFAULT_PAGE_TAG;
pageStack.push(page);
//record
getTaskManager().track(record);
}
}