Android Activity回收与操作超时处理

本文实例为大家分享了Android Activity回收与操作超时的处理,供大家参考,具体内容如下

1、Activity的回收

针对多个activity退出的处理

关键代码:

1)、新建活动管理类:

public class ActivityCollector {
  private static List<Activity> activityList = new ArrayList<Activity>();
  public static void addActivity(Activity activity){
    activityList.add(activity);
  }
  public static void removeActivity(Activity activity){
    activityList.remove(activity);
  }

  public static void finishAllButLast(){
    Activity activity = activityList.get(activityList.size()-1);
    removeActivity(activity);

    for (Activity activityItem: activityList){
      if (!activityItem.isFinishing()){
        activityItem.finish();
      }
    }

    activityList.clear();
    activityList.add(activity);
  }

  public static void finishAll(){
    for (Activity activity: activityList){
      if (!activity.isFinishing()){
        activity.finish();
      }
    }

    activityList.clear();
  }
}

2)、创建基类BaseActivity,并使所有的activity继承自该基类 。在创建时,添加到活动管理器,销毁时,从活动管理器中移除。

public class BaseActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityCollector.addActivity(this);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    ActivityCollector.removeActivity(this);
  }
}

如果需要销毁所有activity,只需调用finishAll()即可

2、操作超时处理

原理:

1)、在activity的stop函数中,根据app进程IMPORTANCE_FOREGROUND判断app在前台或后台
2)、在activity的onResume函数中,做超时检查。

关键代码:

abstract public class TimeOutCheckActivity extends BaseActivity {
  private boolean isLeave = false;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    pref = getSharedPreferences(Constant.CONFIG_NAME, Context.MODE_PRIVATE);
  }

  /**
   * 回调函数,方便测试
   * @return
  */
  abstract protected String getTag();

  ......省略号......

  /***
   * 当用户使程序恢复为前台显示时执行onResume()方法,在其中判断是否超时.
   */
  @Override
  protected void onResume() {
//    Log.i("Back",getTag() + ",onResume,是否在前台:" + isOnForeground());
    super.onResume();
    if (isLeave) {
      isLeave = false;
      timeOutCheck();
    }
  }

  @Override
  protected void onStop() {
    super.onStop();
    if (!isOnForeground()){
      if (!isLeave && isOpenALP()) {
        isLeave = true;
        saveStartTime();
      }
    }
  }

  public void timeOutCheck() {
    long endtime = System.currentTimeMillis();
    if (endtime - getStartTime() >= Constant.TIMEOUT_ALP * 1000) {
      Util.toast(this, "超时了,请重新验证");
      String alp = pref.getString(Constant.ALP, null);
      if (alp == null || alp == "") {
      } else {
        Intent intent = new Intent(this, UnlockGesturePasswordActivity.class);
        intent.putExtra("pattern", alp);
        intent.putExtra("login",false); //手势验证,不进行登录验证
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
        // 打开新的Activity
        startActivityForResult(intent, Constant.REQ_COMPARE_PATTERN_TIMEOUT_CHECK);
      }
    }
  }

  public void saveStartTime() {
    pref.edit().putLong(Constant.START_TIME, System.currentTimeMillis()).commit();
  }

  public long getStartTime() {
    long startTime = 0;
    try {
      startTime = pref.getLong(Constant.START_TIME, 0);
    }catch (Exception e){
      startTime = 0;
    }
    return startTime;
  }

  /**
   * 程序是否在前端运行,通过枚举运行的app实现。防止重复超时检测多次,保证只有一个activity进入超时检测
   *当用户按home键时,程序进入后端运行,此时会返回false,其他情况引起activity的stop函数的调用,会返回true
   * @return
  */
  public boolean isOnForeground() {
    ActivityManager activityManager = (ActivityManager) getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
    String packageName = getApplicationContext().getPackageName();

    List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
    if (appProcesses == null)
      return false;

    for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
      if (appProcess.processName.equals(packageName)
          && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
        return true;
      }
    }

    return false;
  }
}

补充说明:

可以根据importance的不同来判断前台或后台,RunningAppProcessInfo 里面的常量IMTANCE就是上面所说的前台后台,其实IMOPORTANCE是表示这个app进程的重要性,因为系统回收时候,会根据IMOPORTANCE来回收进程的。具体可以去看文档。

public static final int IMPORTANCE_BACKGROUND = 400//后台
public static final int IMPORTANCE_EMPTY = 500//空进程
public static final int IMPORTANCE_FOREGROUND = 100//在屏幕最前端、可获取到焦点 可理解为Activity生命周期的OnResume();
public static final int IMPORTANCE_SERVICE = 300//在服务中
public static final int IMPORTANCE_VISIBLE = 200//在屏幕前端、获取不到焦点可理解为Activity生命周期的OnStart();
(0)

相关推荐

  • Android 暂停和恢复Activity

    暂停和恢复Activity(Pausing and Resuming an Activity) 一个Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务,例如拨号.拍照.发送email.看地图.每一个activity被给予一个窗口,在上面可以绘制用户接口.窗口通常充满屏幕,但也可以小于屏幕而浮于其它窗口之上. 一个应用程序通常由多个activities组成,他们通常是松耦合关系.通常,一个应用程序中的activity被指定为"main"activity,当

  • Android线程管理之ActivityThread

    ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client.ActivityThread.ApplicationThread为Server)负责调度和执行activities.broadcasts和其它操作. 在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity.BroadcastReceiver.Service)都会在同一个进程(

  • Android中子线程和UI线程通信详解

    Android中子线程和UI线程之间通信的详细解释 1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下. 2.首先在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行. 3.Handler: (1).概念: Handler是沟通Activity 与Thread/runnable的桥梁.而Handler是运行在主UI线程中的,它与子线程

  • Android Activity 横竖屏切换的生命周期

    前言 在开发中常要处理横竖屏切换,怎么处理先看生命周期 申明 Activity 横竖屏切换时需要回调两个函数 ,所以在此将这个两个函数暂时看成是Activity 横竖屏切换的生命周期的一部分,这两个函数如下 onSaveInstanceState(Bundle outState) :Activity 即将销毁时保存数据 onRestoreInstanceState(Bundle savedInstanceState) : Activity 重建或者恢复时候取出数据 横竖屏切换生命周期 1.启动程

  • android开发教程之子线程中更新界面

    每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联.Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器.2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了.由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面.

  • Android开发之TabActivity用法实例详解

    本文实例讲述了Android开发之TabActivity用法.分享给大家供大家参考,具体如下: 一.简介 TabActivity继承自Activity,目的是让同一界面容纳更多的内容.TabActivity实现标签页的功能,通过导航栏对各个页面进行管理. 二.XML布局文件 注意: 1.TabActivity的布局文件要求以TabHost作为XML布局文件的根. 2.通常我们采用线性布局,所以<TabHost> 的子元素是 <LinearLayout>. 3.<TabWidg

  • Android实现在子线程中更新Activity中UI的方法

    本文实例讲述了Android实现在子线程中更新Activity中UI的方法.分享给大家供大家参考,具体如下: 在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示.但是,在主线线程之外的线程中直接更新页面显示的问题是:系统会报这个异常: ERROR/AndroidRuntime(1222): android.view.ViewRoot$CalledFromWrongThreadException: Only the original

  • 全面解析Android应用开发中Activity类的用法

    Activity类处于android.app包中,继承体系如下: 1.java.lang.Object 2.android.content.Context 3.android.app.ApplicationContext 4.android.app.Activity activity是单独的,用于处理用户操作.几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当ac

  • android中UI主线程与子线程深入分析

    本文较为深入的分析了android中UI主线程与子线程.分享给大家供大家参考.具体如下: 在一个Android 程序开始运行的时候,会单独启动一个Process.默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process. 一个Android 程序默认情况下也只有一个Process,但一个Pr

  • 详解Android开发中Activity的四种launchMode

    Activity栈主要用于管理Activity的切换.当使用Intent跳转至某个目标Activity,需要根据目标Activity的加载模式来加载. Activity一共有以下四种launchMode: 1.standard:默认,每次使用Intent跳转到目标Activity时都创建一个新的实例.坏处是每次进入都要创建新的实例,执行OnCreate方法. 2.singleTop:如果要跳转的目标Activity正好在task的顶部(说明当前肯定不在目标task里,例如我在微信首页,然后想使用

  • android使用handler ui线程和子线程通讯更新ui示例

    复制代码 代码如下: package com.act262.sockettx; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import and

  • 详解Android Activity之间切换传递数据的方法

    前面照着android系统的裁剪图片的功能自己写了一个相似的工具.功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具,并且获得裁剪后的图片呢? 其实这个也很简单了,就是intent的基础用法. 先上个图(界面依旧没优化,难看就难看吧): 起始activity,打开图片选择窗口,随便选择一张图片 下面是跳转到裁剪界面 按下crop按钮,退出activity,回到原来界面,并显示裁剪后的图 流程就是这样,也算模拟了系统裁剪功能的整体过程.下面就是实现功能的关键代码和说明了.

  • Android动态加载Activity原理详解

    activity的启动流程 加载一个Activity肯定不会像加载一般的类那样,因为activity作为系统的组件有自己的生命周期,有系统的很多回调控制,所以自定义一个DexClassLoader类加载器来加载插件中的Activity肯定是不可以的. 首先不得不了解一下activity的启动流程,当然只是简单的看一下,太详细的话很难研究清楚. 通过startActivity启动后,最终通过AMS进行跨进程回调到ApplicationThread的scheduleLaunchActivity,这时

  • Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

    本文实例讲述了Android实现Activity.Service与Broadcaster三大组件之间互相调用的方法.分享给大家供大家参考,具体如下: 我们研究两个问题, 1.Service如何通过Broadcaster更改activity的一个TextView. (研究这个问题,考虑到Service从服务器端获得消息之后,将msg返回给activity) 2.Activity如何通过Binder调用Service的一个方法. (研究这个问题,考虑到与服务器端交互的动作,打包至Service,Ac

随机推荐