Android开发百科全书②

Posted CodingForAndroid

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发百科全书②相关的知识,希望对你有一定的参考价值。

拆分build.gradle 文件

新建 dependency.gradle 在build.gradle 中添加引用
apply plugin: ‘com.android.application’
apply from:‘dependency.gradle’

例如:

apply plugin: 'com.android.application'
apply from:'aspectj.gradle'
//import org.aspectj.bridge.IMessage
//import org.aspectj.bridge.MessageHandler
//import org.aspectj.tools.ajc.Main

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
//        classpath 'org.aspectj:aspectjtools:1.8.1'
    

repositories 
    mavenCentral()


android 


    compileSdkVersion 25
    buildToolsVersion '26.0.2'

    defaultConfig 
        applicationId 'com.example.myaspectjapplication'
        minSdkVersion 16
        targetSdkVersion 25
    

    lintOptions 
        abortOnError true
    


//final def log = project.logger
//final def variants = project.android.applicationVariants
//
//variants.all  variant ->
//    if (!variant.buildType.isDebuggable()) 
//        log.debug("Skipping non-debuggable build type '$variant.buildType.name'.")
//        return;
//    
//
//    JavaCompile javaCompile = variant.javaCompile
//    javaCompile.doLast 
//        String[] args = ["-showWeaveInfo",
//                         "-1.5",
//                         "-inpath", javaCompile.destinationDir.toString(),
//                         "-aspectpath", javaCompile.classpath.asPath,
//                         "-d", javaCompile.destinationDir.toString(),
//                         "-classpath", javaCompile.classpath.asPath,
//                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
//        log.debug "ajc args: " + Arrays.toString(args)
//
//        MessageHandler handler = new MessageHandler(true);
//        new Main().run(args, handler);
//        for (IMessage message : handler.getMessages(null, true)) 
//            switch (message.getKind()) 
//                case IMessage.ABORT:
//                case IMessage.ERROR:
//                case IMessage.FAIL:
//                    log.error message.message, message.thrown
//                    break;
//                case IMessage.WARNING:
//                    log.warn message.message, message.thrown
//                    break;
//                case IMessage.INFO:
//                    log.info message.message, message.thrown
//                    break;
//                case IMessage.DEBUG:
//                    log.debug message.message, message.thrown
//                    break;
//            
//        
//    
//
dependencies 
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', 
        exclude group: 'com.android.support', module: 'support-annotations'
    )
    //compile 'com.android.support:appcompat-v7:25.3.1'
    //compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
//    compile project(':gintonic')
//    compile 'org.aspectj:aspectjrt:1.8.1'


import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

buildscript 
    repositories 
        mavenCentral()
    
    dependencies 
        classpath 'org.aspectj:aspectjtools:1.8.1'
    

repositories 
    mavenCentral()


android 
    compileSdkVersion 25
    buildToolsVersion '26.0.2'

    defaultConfig 
        minSdkVersion 16
        targetSdkVersion 25
    



final def log = project.logger
final def variants = project.android.applicationVariants

variants.all  variant ->
//    if (!variant.buildType.isDebuggable()) 
//        log.debug("Skipping non-debuggable build type '$variant.buildType.name'.")
//        return;
//    

    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast 
        String[] args = ["-showWeaveInfo",
                         "-1.5",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler);
        for (IMessage message : handler.getMessages(null, true)) 
            switch (message.getKind()) 
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                    log.warn message.message, message.thrown
                    break;
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            
        
    

dependencies 
    compile project(':gintonic')
    compile 'org.aspectj:aspectjrt:1.8.1'


GridView 实现单双行切换setNumColumns问题

GridView 实现单双行切换setNumColumns问题导致itemView中的TextView ,设置gravity和padding时后,导致setText中的文字消失。解决办法,setNumColumns后 再setAdapter 。 原因应该跟绘制有关系。

	int FirstVisiblePosition = mGridView.getFirstVisiblePosition();
	mGridView.setNumColumns(1);
	mGridView.setSelection(FirstVisiblePosition);
	mGridView.setAdapter(adapter);

Android 安全退出App完美实现

https://blog.csdn.net/csdn_mm/article/details/80620265
一种是基于Activity的启动模式singleTask模式实现的,一种是基于全局Activity管理类实现的。强烈推荐第一种方法实现,简单又方便。

基于Activity的启动模式singleTask模式实现
singleTask是Activity启动模式中的一种,当startActivity时,它先会在当前栈中查询是否存在Activity的实例,如果存在,则将其置于栈顶,并将其之上的所有Activity移出栈。同时调用Activity的onNewIntent方法。可以看出实现安全退出APP很简单,只需要将MainActivity的launchMode改为singleTask,在MainActivity中的onNewintent方法中finish掉当前Activity即可。
说下环境:MainActivity跳转到FirstActivity,FirstActivity跳转到secondActivity,在secondActivity中退出程序。
首先,将MainActivity的launchMode改为singleTask,如下

<activity
            android:name=".MainActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

其次 实现MainActivity中的onNewIntent方法,实现退出APP的逻辑。

 @Override
    protected void onNewIntent(Intent intent) 
        super.onNewIntent(intent);
        String tag = intent.getStringExtra("EXIT_TAG");
        if (tag != null&& !TextUtils.isEmpty(tag)) 
            if ("SINGLETASK".equals(tag)) //退出程序
                finish();
            
        
    

这里面的tag用来标识关闭app的,在secondActivity中退出APP调用startActivity的时候需要传入。
现在就看下secondActivity中相关代码

 Intent intent = new Intent(this, MainActivity.class);
                intent.putExtra("EXIT_TAG", "SINGLETASK");
                startActivity(intent);

通过这三步就解决了安全退出APP的问题,现在很多人都在用,你还在等啥。

Android ListView等getView调用多次问题

如果我们将ListView的高度设置为wrap_content时ListView会去调用getView去动态计算高度,
这样的话导致ListView会再次调用getView去渲染视图。所以建议,将ListView的高度设置成一个固定的值或者match_parent,这样的话,会啊减少调用次数。

Intent.addFlags() 启动Activity的20种flags全解析

https://www.jianshu.com/p/2bdc16cba04f
简介

Activity是四大组件中最重要的一个,也是平时开发中接触最多的。与Activity启动行为相关的就是它的启动模式,Standard、SingleTop、SingleTask、SingleInstance这4种launchMode相信大家不陌生,如果不太熟悉可以看这里:

https://www.jianshu.com/p/c34483bb5c0f

OK,熟悉了4种launchMode后相信你已经对Activity任务栈有一些理解了,能应对一些常见的开发场景了。然而,除了4种launchMode,还有更复杂的控制Activity行为的方式,那就是给启动Activity的Intent添加flag,使用 Intent.addFlags(int flags) 方法。看一下这个方法的参数,总共有20种:

    Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT,
    Intent.FLAG_ACTIVITY_CLEAR_TASK,
    Intent.FLAG_ACTIVITY_CLEAR_TOP,
    Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET,
    Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,
    Intent.FLAG_ACTIVITY_FORWARD_RESULT,
    Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY,
    Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT,
    Intent.FLAG_ACTIVITY_MULTIPLE_TASK,
    Intent.FLAG_ACTIVITY_NEW_DOCUMENT,
    Intent.FLAG_ACTIVITY_NEW_TASK,
    Intent.FLAG_ACTIVITY_NO_ANIMATION,
    Intent.FLAG_ACTIVITY_NO_HISTORY,
    Intent.FLAG_ACTIVITY_NO_USER_ACTION,
    Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,
    Intent.FLAG_ACTIVITY_REORDER_TO_FRONT,
    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED,
    Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS,
    Intent.FLAG_ACTIVITY_SINGLE_TOP,
    Intent.FLAG_ACTIVITY_TASK_ON_HOME,

这么多估计大家一看就晕了,我一开始也是这样。不过,仔细看每一条的文档,把它添加到你要启动的Activity上,然后观察Activity的行为,这样就容易弄明白它的含义。

相关概念

在分析具体的flag之前,介绍一些Activity任务栈相关的概念:Activity、task、tasks、recent tasks list。这些概念都是抽象的,除了Activity和recent tasks list看得见之外,其他都是看不见摸不着的。如果没有直观的视觉感受,即使我说得天花乱坠你也可能还是云里雾里,而有了图甚至动画直接展示它们就不一样了。下面这个工具能很好地帮助我们:

https://github.com/rome753/ActivityTaskView

有了ActivityTaskView,就能结合图来分析了。

  1. Activity 活动,这个就不用解释了

  2. task 任务

它是应用中的放置活动的一个类似于栈的结构。栈顶的是最上面的活动,也就是用户直接看到的页面,顶部以下的活动都处于onStop状态(如果是可见的,那么处于onPause状态)。一般连续按返回键能自顶向下销毁活动。上图中的悬浮窗表示一个任务,在这个任务中启动了20多个活动。

  1. tasks 一个应用的所有任务

虽然单个task是比较常见的应用,但是一个应用可以有多个task,创建新的task有好几种方法。上图中的悬浮窗的每一列表示一个任务,在这个应用中一共创建了三个任务。

  1. recent tasks list 最近任务列表

老的安卓系统中长按home键出现的页面,新的系统直接按导航栏中的正方形按钮。这个列表表示最近启动的应用的tasks,表中每一项表示一个入口。需要注意的是,一个应用可能会出现多个入口,因为应用可能有多个任务,当然不一定每个任务都会出现在列表中。

分析flags

下面结合动画来分析Intent中添加的flags。

  1. FLAG_ACTIVITY_CLEAR_TASK
    /**
     * If set in an Intent passed to @link Context#startActivity Context.startActivity(),
     * this flag will cause any existing task that would be associated with the
     * activity to be cleared before the activity is started.  That is, the activity
     * becomes the new root of an otherwise empty task, and any old activities
     * are finished.  This can only be used in conjunction with @link #FLAG_ACTIVITY_NEW_TASK.
     */
  1. 本flag能造成在新活动启动前,与新活动关联的任务被清空。也就是说,新活动成为新任务的根,旧的活动都被结束了。本flag只能与FLAG_ACTIVITY_NEW_TASK联合使用。

public static final int FLAG_ACTIVITY_CLEAR_TASK = 0X00008000;

  1. FLAG_ACTIVITY_CLEAR_TOP
    /**
     * If set, and the activity being launched is already running in the
     * current task, then instead of launching a new instance of that activity,
     * all of the other activities on top of it will be closed and this Intent
     * will be delivered to the (now on top) old activity as a new Intent.
     *
     * <p>For example, consider a task consisting of the activities: A, B, C, D.
     * If D calls startActivity() with an Intent that resolves to the component
     * of activity B, then C and D will be finished and B receive the given
     * Intent, resulting in the stack now being: A, B.
     *
     * <p>The currently running instance of activity B in the above example will
     * either receive the new intent you are starting here in its
     * onNewIntent() method, or be itself finished and restarted with the
     * new intent.  If it has declared its launch mode to be "multiple" (the
     * default) and you have not set @link #FLAG_ACTIVITY_SINGLE_TOP in
     * the same intent, then it will be finished and re-created; for all other
     * launch modes or if @link #FLAG_ACTIVITY_SINGLE_TOP is set then this
     * Intent will be delivered to the current instance's onNewIntent().
     *
     * <p>This launch mode can also be used to good effect in conjunction with
     * @link #FLAG_ACTIVITY_NEW_TASK: if used to start the root activity
     * of a task, it will bring any currently running instance of that task
     * to the foreground, and then clear it to its root state.  This is
     * especially useful, for example, when launching an activity from the
     * notification manager.
     *
     * <p>See
     * <a href="@docRootguide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back
     * Stack</a> for more information about tasks.
     */
  1. 新活动已在当前任务中时,在新活动上面的活动会被关闭,新活动不会重新启动,只会接收new intent。
  2. 新活动已在任务最上面时:如果启动模式是"multiple" (默认的),并且没添加FLAG_ACTIVITY_SINGLE_TOP,那么活动会被销毁重新创建;如果启动模式是其他的,或者添加了FLAG_ACTIVITY_SINGLE_TOP,那么只会调用活动的onNewIntent()。
  3. 跟FLAG_ACTIVITY_NEW_TASK联合使用效果很好:如果用于启动一个任务中的根活动,会把该任务移到前面并清空至root状态。这特别有用,比如用于从notification manager中启动活动。

clearTop.gif

public static final int FLAG_ACTIVITY_CLEAR_TOP = 0x04000000;

  1. FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET

    /**

    • @deprecated As of API 21 this performs identically to
    • @link #FLAG_ACTIVITY_NEW_DOCUMENT which should be used instead of this.
      */
  2. 已废弃。API 21后用FLAG_ACTIVITY_NEW_DOCUMENT。

clearWhenTaskReset.gif

public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000;

  1. FLAG_ACTIVITY_MULTIPLE_TASK

    /**

    • This flag is used to create a new task and launch an activity into it.
    • This flag is always paired with either @link #FLAG_ACTIVITY_NEW_DOCUMENT
    • or @link #FLAG_ACTIVITY_NEW_TASK. In both cases these flags alone would
    • search through existing tasks for ones matching this Intent. Only if no such
    • task is found would a new task be created. When paired with
    • FLAG_ACTIVITY_MULTIPLE_TASK both of these behaviors are modified to skip
    • the search for a matching task and unconditionally start a new task.
    • When used with @link #FLAG_ACTIVITY_NEW_TASK do not use this
    • flag unless you are implementing your own
    • top-level application launcher. Used in conjunction with
    • @link #FLAG_ACTIVITY_NEW_TASK to disable the
    • behavior of bringing an existing task to the foreground. When set,
    • a new task is always started to host the Activity for the
    • Intent, regardless of whether there is already an existing task running
    • the same thing.
    • Because the default system does not include graphical task management,

    • you should not use this flag unless you provide some way for a user to
    • return back to the tasks you have launched.
    • See @link #FLAG_ACTIVITY_NEW_DOCUMENT for details of this flag’s use for
    • creating new document tasks.
    • This flag is ignored if one of @link #FLAG_ACTIVITY_NEW_TASK or

    • @link #FLAG_ACTIVITY_NEW_DOCUMENT is not also set.
    • See

    • Tasks and Back
    • Stack for more information about tasks.
    • @see #FLAG_ACTIVITY_NEW_DOCUMENT
    • @see #FLAG_ACTIVITY_NEW_TASK
      */
  2. 用于创建一个新任务,并启动一个活动放进去;
    总是跟FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK一起使用;
    单独用FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK时,会在已存在的任务中寻找匹配的Intent,找不到才会创建一个新任务;
    使用了本flag不会寻找匹配的Intent,无条件创建一个新任务。

  3. 用了FLAG_ACTIVITY_NEW_TASK就不要用本flag,除非你启动的是应用的launcher。 跟FLAG_ACTIVITY_NEW_TASK联合使用能防止把已存在的任务移到前面,会为新活动创建一个新任务,无论已存在的任务中有没有新活动。

  4. 因为默认安卓系统中没有提供可视化的任务管理,所以你不应该使用本flag,除非给用户提供可以回到其他任务的方法。

  5. 单独用本flag而不用FLAG_ACTIVITY_NEW_DOCUMENT或者FLAG_ACTIVITY_NEW_TASK是无效的。

multiTask1.gif

multiTask2.gif

public static final int FLAG_ACTIVITY_MULTIPLE_TASK = 0x08000000;

  1. FLAG_ACTIVITY_NEW_DOCUMENT

    /**

    • This flag is used to open a document into a new task rooted at the activity launched
    • by this Intent. Through the use of this flag, or its equivalent attribute,
    • @link android.R.attr#documentLaunchMode multiple instances of the same activity
    • containing different documents will appear in the recent tasks list.
    • The use of the activity attribute form of this,

    • @link android.R.attr#documentLaunchMode, is
    • preferred over the Intent flag described here. The attribute form allows the
    • Activity to specify multiple document behavior for all launchers of the Activity
    • whereas using this flag requires each Intent that launches the Activity to specify it.
    • Note that the default semantics of this flag w.r.t. whether the recents entry for

    • it is kept after the activity is finished is different than the use of
    • @link #FLAG_ACTIVITY_NEW_TASK and @link android.R.attr#documentLaunchMode – if
    • this flag is being used to create a new recents entry, then by default that entry
    • will be removed once the activity is finished. You can modify this behavior with
    • @link #FLAG_ACTIVITY_RETAIN_IN_RECENTS.
    • FLAG_ACTIVITY_NEW_DOCUMENT may be used in conjunction with @link

    • #FLAG_ACTIVITY_MULTIPLE_TASK. When used alone it is the
    • equivalent of the Activity manifest specifying @link
    • android.R.attr#documentLaunchMode=“intoExisting”. When used with
    • FLAG_ACTIVITY_MULTIPLE_TASK it is the equivalent of the Activity manifest specifying
    • @link android.R.attr#documentLaunchMode=“always”.
    • Refer to @link android.R.attr#documentLaunchMode for more information.
    • @see android.R.attr#documentLaunchMode
    • @see #FLAG_ACTIVITY_MULTIPLE_TASK
      */
  2. 本flag会给启动的活动开一个新的任务记录。使用了本flag或documentLaunchMode属性时,相同活动的多实例会在最近任务列表中产生不同的记录。

  3. 使用本flag比使用documentLaunchMode属性更好,因为documentLaunchMode属性会跟活动绑定,而flag只在需要时添加。

  4. 注意本flag的默认词义,活动销毁后最近任务列表中的入口不会移除。这跟使用FLAG_ACTIVITY_NEW_TASK不一样,后者活动销毁后入口会马上移除。你可以用FLAG_ACTIVITY_RETAIN_IN_RECENTS改变这个行为。

  5. 本flag可以跟FLAG_ACTIVITY_MULTIPLE_TASK联合使用。单独使用时跟manifest活动中定义documentLaunchMode="intoExisting"效果相同,联合使用时跟manifest活动中定义documentLaunchMode="always"效果相同。

newDocument.gif

public static final int FLAG_ACTIVITY_NEW_DOCUMENT = FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;

  1. FLAG_ACTIVITY_NEW_TASK

    /**

    • If set, this activity will become the start of a new task on this
    • history stack. A task (from the activity that started it to the
    • next task activity) defines an atomic group of activities that the
    • user can move to. Tasks can be moved to the foreground and background;
    • all of the activities inside of a particular task always remain in
    • the same order. See
    • Tasks and Back
    • Stack for more information about tasks.
    • This flag is generally used by activities that want

    • to present a “launcher” style behavior: they give the user a list of
    • separate things that can be done, which otherwise run completely
    • independently of the activity launching them.
    • When using this flag, if a task is already running for the activity

    • you are now starting, then a new activity will not be started; instead,
    • the current task will simply be brought to the front of the screen with
    • the state it was last in. See @link #FLAG_ACTIVITY_MULTIPLE_TASK for a flag
    • to disable this behavior.
    • This flag can not be used when the caller is requesting a result from

    • the activity being launched.
      */
  2. 新活动会成为历史栈中的新任务(一组活动)的开始。

  3. 通常用于具有"launcher"行为的活动:让用户完成一系列事情,完全独立于之前的活动。

  4. 如果新活动已存在于一个为它运行的任务中,那么不会启动,只会把该任务移到屏幕最前。

  5. 如果新活动要返回result给启动自己的活动,就不能用这个flag。

newTask.gif

public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;

  1. FLAG_ACTIVITY_NO_ANIMATION

    /**

    • If set in an Intent passed to @link Context#startActivity Context.startActivity(),
    • this flag will prevent the system from applying an activity transition
    • animation to go to the next activity state. This doesn’t mean an
    • animation will never run – if another activity change happens that doesn’t
    • specify this flag before the activity started here is displayed, then
    • that transition will be used. This flag can be put to good use
    • when you are going to do a series of activity operations but the
    • animation seen by the user shouldn’t be driven by the first activity
    • change but rather a later one.
      */
  2. 本flag会阻止系统展示活动的当前状态到另一个状态之间的转移动画。这并不意味着永远没有动画 – 如果另一项活动的改变在当前展示的活动启动前发生并且没有使用本flag,那么动画还会展示。当你要进行一系列活动操作,但是用户看到的动画不应该由第一项改变来驱动,而是由下一项。

noAnimation.gif

public static final int FLAG_ACTIVITY_NO_ANIMATION = 0X00010000;

  1. FLAG_ACTIVITY_NO_HISTORY

    /**

    • If set, the new activity is not kept in the history stack. As soon as
    • the user navigates away from it, the activity is finished. This may also
    • be set with the @link android.R.styleable#AndroidManifestActivity_noHistory
    • noHistory attribute.
    • If set, @link android.app.Activity#onActivityResult onActivityResult()

    • is never invoked when the current activity starts a new activity which
    • sets a result and finishes.
      */
  2. 新活动不会保留在历史栈中,一旦用户切换到其他页面,新活动会马上销毁。

  3. 旧活动的onActivityResult()方法永远不会被触发。

noHistory.gif

public static final int FLAG_ACTIVITY_NO_HISTORY = 0x40000000;

  1. FLAG_ACTIVITY_REORDER_TO_FRONT

    /**

    • If set in an Intent passed to @link Context#startActivity Context.startActivity(),
    • this flag will cause the launched activity to be brought to the front of its
    • task’s history stack if it is already running.
    • For example, consider a task consisting of four activities: A, B, C, D.

    • If D calls startActivity() with an Intent that resolves to the component
    • of activity B, then B will be brought to the front of the history stack,
    • with this resulting order: A, C, D, B.
    • This flag will be ignored if @link #FLAG_ACTIVITY_CLEAR_TOP is also
    • specified.
      */
  2. 如果新活动已在任务中,用本flag启动会将它移到任务的历史栈的前面。

  3. 如果用了FLAG_ACTIVITY_CLEAR_TOP,本flag就无效。

reorderToFront.gif

public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000;

  1. FLAG_ACTIVITY_RETAIN_IN_RECENTS

    /**

    • By default a document created by @link #FLAG_ACTIVITY_NEW_DOCUMENT will
    • have its entry in recent tasks removed when the user closes it (with back
    • or however else it may finish()). If you would like to instead allow the
    • document to be kept in recents so that it can be re-launched, you can use
    • this flag. When set and the task’s activity is finished, the recents
    • entry will remain in the interface for the user to re-launch it, like a
    • recents entry for a top-level application.
    • The receiving activity can override this request with
    • @link android.R.attr#autoRemoveFromRecents or by explcitly calling
    • @link android.app.Activity#finishAndRemoveTask()
    • Activity.finishAndRemoveTask().
      */
  2. 默认情况下由FLAG_ACTIVITY_NEW_DOCUMENT创建的新纪录,用户关闭时(按返回键或其他方式结束)它在最近任务中的入口会被移除。如果你想保留入口,就用本flag。

  3. 接收的活动可以用autoRemoveFromRecents属性或者调用Activity.finishAndRemoveTask()来覆盖本请求。

retainInRecents.gif

public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 0x00002000;

  1. FLAG_ACTIVITY_SINGLE_TOP

    /**

    • If set, the activity will not be launched if it is already running
    • at the top of the history stack.
      */
  2. 新活动已存在历史栈的顶端时就不会重新启动。

singleTop.gif

public static final int FLAG_ACTIVITY_SINGLE_TOP = 0x20000000;

  1. FLAG_ACTIVITY_FORWARD_RESULT

    /**

    • If set and this intent is being used to launch a new activity from an
    • existing one, then the reply target of the existing activity will be
    • transfered to the new activity. This way the new activity can call
    • @link android.app.Activity#setResult and have that result sent back to
    • the reply target of the original activity.
      */
  2. (当前活动由源活动启动)本intent从当前活动启动新活动时,源活动的接收目标会从当前活动转移为新活动。新活动调用setResult的数据会传送给源活动。

public static final int FLAG_ACTIVITY_FORWARD_RESULT = 0x02000000;
13. FLAG_ACTIVITY_PREVIOUS_IS_TOP

/**
 * If set and this intent is being used to launch a new activity from an
 * existing one, the current activity will not be counted as the top
 * activity for deciding whether the new intent should be delivered to
 * the top instead of starting a new one.  The previous activity will
 * be used as the top, with the assumption being that the current activity
 * will finish itself immediately.
 */
  1. 本intent从当前活动启动新活动时,当前活动不会被视为顶端活动,不管是决定传intent给顶端还是启动新活动。新活动被当做顶端活动使用,假设当前活动立即销毁了。

public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 0x01000000;
14. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

/**
 * If set, the new activity is not kept in the list of recently launched
 * activities.
 */
  1. 新活动不会保存在最近启动的活动列表中。

public static final int FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS = 0x00800000;
15. FLAG_ACTIVITY_BROUGHT_TO_FRONT

/**
 * This flag is not normally set by application code, but set for you by
 * the system as described in the
 * @link android.R.styleable#AndroidManifestActivity_launchMode
 * launchMode documentation for the singleTask mode.
 */
  1. 本flag一般不由应用代码设置,singleTask模式时系统会给你设置。

public static final int FLAG_ACTIVITY_BROUGHT_TO_FRONT = 0x00400000;
16. FLAG_ACTIVITY_RESET_TASK_IF_NEEDED

/**
 * If set, and this activity is either being started in a new task or
 * bringing to the top an existing task, then it will be launched as
 * the front door of the task.  This will result in the application of
 * any affinities needed to have that task in the proper state (either
 * moving activities to or from it), or simply resetting that task to
 * its initial state if needed.
 */
  1. 新活动在新任务中启动或者被放到一个已存在任务的顶端时,会被当做任务的前门来启动。这会导致任何相关性的活动在适当状态下需要拥有这个任务(无论移动活动到它里面或者是移走),或者在需要时简单地重置任务到初始状态。

public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 0x00200000;
17. FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY

/**
 * This flag is not normally set by application code, but set for you by
 * the system if this activity is being launched from history
 * (longpress home key).
 */
  1. 本flag一般不由应用代码设置,活动从历史栈中启动(长按home键)时系统会给你设置。

public static final int FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY = 0x00100000;
18. FLAG_ACTIVITY_NO_USER_ACTION

/**
 * If set, this flag will prevent the normal @link android.app.Activity#onUserLeaveHint
 * callback from occurring on the current frontmost activity before it is
 * paused as the newly-started activity is brought to the front.
 *
 * <p>Typically, an activity can rely on that callback to indicate that an
 * explicit user action has caused their activity to be moved out of the
 * foreground. The callback marks an appropriate point in the activity's
 * lifecycle for it to dismiss any notifications that it intends to display
 * "until the user has seen them," such as a blinking LED.
 *
 * <p>If an activity is ever started via any non-user-driven events such as
 * phone-call receipt or an alarm handler, this flag should be passed to @link
 * Context#startActivity Context.startActivity, ensuring that the pausing
 * activity does not think the user has acknowledged its notification.
 */
  1. 本flag会阻止当前最前面活动的onUserLeaveHint回调,在它被新启动的活动造成paused状态时。
  2. 通常,一个活动在受到用户操作而从前面移走的时候会调用上面的回调。该回调标志着活动生命周期中的一个点,在该点活动会隐藏它想要显示的”直到用户看到“的东西,比如闪烁的LED灯。
  3. 如果一个活动曾经由非用户驱动的事件比如来电或闹钟启动,应该在startActivity中添加本flag,以保证暂停时活动知道用户并没有看到通知。

public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000;
19. FLAG_ACTIVITY_TASK_ON_HOME

/**
 * If set in an Intent passed to @link Context#startActivity Context.startActivity(),
 * this flag will cause a newly launching task to be placed on top of the current
 * home activity task (if there is one).  That is, pressing back from the task
 * will always return the user to home even if that was not the last activity they
 * saw.   This can only be used in conjunction with @link #FLAG_ACTIVITY_NEW_TASK.
 */
  1. 本flag会造成新的启动任务放在当前主页活动任务(如果有的话)的顶端。也就是说,在任务中按返回键总是会回到主页,即使上一个用户看到的活动不是主页。本flag只能与FLAG_ACTIVITY_NEW_TASK联合使用。

public static final int FLAG_ACTIVITY_TASK_ON_HOME = 0X00004000;
20. FLAG_ACTIVITY_LAUNCH_ADJACENT

/**
 * This flag is only used in split-screen multi-window mode. The new activity will be displayed
 * adjacent to the one launching it. This can only be used in conjunction with
 * @link #FLAG_ACTIVITY_NEW_TASK. Also, setting @link #FLAG_ACTIVITY_MULTIPLE_TASK is
 * required if you want a new instance of an existing activity to be created.
 */
  1. 本flag只在分屏多窗口模式下使用。新活动会显示在旧活动旁边。本flag只能跟FLAG_ACTIVITY_NEW_TASK联合使用。并且如果你想创建一个已存在活动的新实例,那么要设置FLAG_ACTIVITY_MULTIPLE_TASK。

public static final int FLAG_ACTIVITY_LAUNCH_ADJACENT = 0x00001000

Activity的启动模式:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT

https://blog.csdn.net/u012207345/article/details/73485450
注:.

四种:

  1. standard 被启动就会创建一个新的

  2. singleTop 栈顶单实例(当该activity处于task栈顶时,可以复用,直接onNewIntent)

  3. singleTask 栈中单实例(oncreate该activity并销毁在他之上的其他activity)

  4. singleInstance 全局单实例(应用场景:地图,Activity初始化需要大量资源)

Intent的标志位FLAG:

Intent.FLAG_ACTIVITY_SINGLE_TOP 与加载模式singleTop功能相同

Intent.FLAG_ACTIVITY_CLEAR_TOP 销毁目标Activity和它之上的所有Activity,重新创建目标Activity

Intent.FLAG_ACTIVITY_NEW_TASK

=其他===================================

  1. 如果已经启动了四个Activity:A,B,C和D。在D Activity里,我们要跳到B Activity,同时希望C finish掉,可以在startActivity(intent)里的intent里添加flags标记,如下所示:
Intent intent = new Intent(this, B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

这样启动B Activity,就会把D,C都finished掉,如果你的B Activity的启动模式是默认的(multiple) ,则B Activity会finished掉,再启动一个新的Activity B。

如果不想重新再创建一个新的B Activity,则在上面的代码里再加上:

intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

这样B Activity就会再创建一个新的了,而是会重用之前的B Activity,同时调用B Activity的onNewIntent()方法。

  1. 如果已经启动了四个Activity:A,B,C和D,在D Activity里,想再启动一个Actvity B,但不变成A,B,C,D,B,而是希望是A,C,D,B,则可以像下面写代码:
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);

只生成一个Activity实例===========

在一个Activity中,多次调用startActivity()来启动另一个Activity,要想只生成一个Activity实例,方法有两种。

方法一:设置起动模式

一个Activity有四种启动模式:standard, singleTop, singleTask, singleInstance。

standard: 标准模式,一调用startActivity()方法就会产生一个新的实例。

singleTop: 如果已经有一个实例位于Activity栈的顶部时,就不产生新的实例,而只是调用Activity中的newInstance()方法。如果不位于栈顶,会产生一个新的实例。

singleTask: 会在一个新的task中产生这个实例,以后每次调用都会使用这个,不会去产生新的实例了。

singleInstance: 这个跟singleTask基本上是一样,只有一个区别:在这个模式下的Activity实例所处的task中,只能有这个activity实例,不能有其他的实例。

这些启动模式可以在功能清单文件中进行设置,中的launchMode属性。

方法二:在intent中加标志

Intent.FLAG_ACTIVITY_REORDER_TO_FRONT这个标志表示:如果这个activity已经启动了,就不产生新的activity,而只是把这个activity实例加到栈顶来就可以了。

代码如下:

Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);   
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);   
startActivity(intent);

Activity常见Flags(CLEAR_TOP与各种Activity启动模式连用详解)

https://blog.csdn.net/yztbydh/article/details/80450615
Activity有很多Flag ,一些Flag可以用来设置启动模式,一些可以用来影响Activity的运行状态,这里介绍常见的FLAG

一般通过在Intent设置:

Intent intent = new Intent();
intent.setFlag(XXFLAG | XXXFLAG);

一、更改Activity启动模式

FLAG_ACTIVITY_NEW_TASK

相当于在xml中指定singleTask模式:

intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);

FLAG_ACTIVITY_SINGLE_TOP

相当于在xml中指定singleTop模式:

intent.setFlag(Intent.FLAG_ACTIVITY_SINGLE_TOP);

二、更改Activity运行状态

1 FLAG_ACTIVITY_CLEAR_TOP

具有此标记位的Activity在同一个任务栈中,所有位于它上面的Activity都要出栈

1.1 与FLAG_ACTIVITY_NEW_TASK配合使用

相当于在XML中指定SingleTask“

1.2 ClearTop与各种Activity启动模式连用

1.2.1 与Standard

1.2.2 与SingleTop

1.2.3 与SingleTask

1.2.4 与SingleInstance

  1. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有此标记的Activity不会出现在历史Activity列表中
相当于在xml中指定:

android:excludeFromRecents="true"

scrollview嵌套RecyclerView总是item显示不全

在RecyclerView外层在套一层RelativeLayout.即可完美解决ScrollView嵌套RecyclerView高度问题.

ScrollView内部嵌套Recyclerview,防止recyclerview自动获得焦点

在ScrollView下面的LinearLayout加上android:descendantFocusability="blocksDescendants"属性,

关于RecyclerView.setOnClickListener(…)无效的解决方案

直接留干货了
setOnClickListener()是父类的方法,RecyclerView重写了onTouch事件没有去理会父类的Listener,导致OnClickListener失效,
解决方法是:

gestureDetector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() 
    @Override
    public boolean onDown(MotionEvent e) 
        return false;
    

    @Override
    public void onShowPress(MotionEvent e) 

    

    @Override
    public boolean onSingleTapUp(MotionEvent e) 
        // do something
        return true;
    

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 
        return false;
    

    @Override
    public void onLongPress(MotionEvent e) 

    

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 
        return false;
    
);

mRecycler.setOnTouchListener(new View.OnTouchListener() 
    @Override
    public boolean onTouch(View v, MotionEvent event) 
        return gestureDetector.onTouchEvent(event);
    
);

关于GestureDetector,请看这里http://blog.csdn.net/totond/article/details/77881180

RecyclerView导致自身和父控件点击事件无效

最近有一个需求,RecyclerView外层嵌套了一个LinearLayout,想实现点击整个LinearLayout都能响应一个事件,结果给LinearLayout和RecyclerView都加上点击事件(非itemClick)后,点击RecyclerView范围无效。可能是RecyclerView的item截获了click事件,阻止了点击的透传,做了以下处理解决

recyclerView.setOnTouchListener(new View.OnTouchListener() 
    @Override
    public boolean onTouch(View v, MotionEvent event) 
        if (event.getAction() == MotionEvent.ACTION_UP) 
            myLayout.performClick();  //模拟父控件的点击
        
        return false;
    
);

jar 解压缩后重新压缩成jar包

cmd 在jar 解压缩的目录下 输入 jar cvf0M name.jar ./

就能重新打包成jar。

一.jar命令参数:

jar命令格式:jar c t x u f [ v m e 0 M i ][-C 目录]文件名…

其中ctxu这四个参数必须选选其一。[v f m e 0 M i ]是可选参数,文件名也是必须的。

-c 创建一个jar包
-t 显示jar中的内容列表
-x 解压jar包
-u 添加文件到jar包中
-f 指定jar包的文件名
-v 生成详细的报造,并输出至标准设备
-m 指定manifest.mf文件.(manifest.mf文件中可以对jar包及其中的内容作一些一设置)
-0 产生jar包时不对其中的内容进行压缩处理
-M 不产生所有文件的清单文件(Manifest.mf)。这个参数与忽略掉-m参数的设置
-i 为指定的jar文件创建索引文件
-C 表示转到相应的目录下执行jar命令,相当于cd到那个目录,然后不带-C执行jar命令

Android多进程时Application初始化问题,大坑

之前在做项目时,遇到一个大坑,就是我的APP 的Application 的onCreate方法,竟然执行了好几次,这就导致我在onCreate里面做了一些初始化的操作被重复执行了,导致奇怪的bug产生。后来冷静下来分析一下,才发现有一些第三方组件,比如百度推送之类的,它们是单独开了一个进程,那么每个进程会自己初始化自己的Application,那自然onCreate方法会多次执行。准确的说就是你的APP里有多少个进程,就会初始化多少次Application 。

但是有的东西就是只需要在Application 的onCreate 里只初始化一次。那怎么解决呢?看代码:

public class MyApplication extends Application 
    private final static String PROCESS_NAME = "com.test";
    private static MyApplication myApplication = null;
 
    public static MyApplication getApplication() 
        return myApplication;
    
 
    /**
     * 判断是不是UI主进程,因为有些东西只能在UI主进程初始化
     */
    public static boolean isAppMainProcess() 
        try 
            int pid = android.os.Process.myPid();
            String process = getAppNameByPID(MyApplication.getApplication(), pid);
            if (TextUtils.isEmpty(process)) 
                return true;
             else if (PROCESS_NAME.equalsIgnoreCase(process)) 
                return true;
             else 
                return false;
            
         catch (Exception e) 
            e.printStackTrace();
            return true;
        
    
 
    /**
     * 根据Pid得到进程名
     */
    public static String getAppNameByPID(Context context, int pid) 
        ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        for (android.app.ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) 
            if (processInfo.pid == pid) 
                return processInfo.processName;
            
        
        return "";
    
 
    @Override
    public void onCreate() 
        super.onCreate();
 
        myApplication = this;
 
        if (isAppMainProcess()) 
            //do something for init
        
    

这样就保证了可以只初始化一次。

刷新RecylerView,item数据错位

adapter有个setHasStableIds(boolean )方法
“给每个item一个唯一的标志id”,这样当adapter调用notifyDatasetChanced的时候,会根据item的id来辨别每个item,因此在给recylerview设置adapter前 加上 adapter.setHasStableIds(true),就可以解决这个bug。

透明度中百分比与十六进制的对应关系

100% — FF
99% — FC
98% — FA
97% — F7
96% — F5
95% — F2
94% — F0
93% — ED
92% — EB
91% — E8
90% — E6
89% — E3
88% — E0
87% — DE
86% — DB
85% — D9
84% — D6
83% — D4
82% — D1
81% — CF
80% — CC
79% — C9
78% — C7
77% — C4
76% — C2
75% — BF
74% — BD
73% — BA
72% — B8
71% — B5
70% — B3
69% — B0
68% — AD
67% — AB
66% — A8
65% — A6
64% — A3
63% — A1
62% — 9E
61% — 9C
60% — 99
59% — 96
58% — 94
57% — 91
56% — 8F
55% — 8C
54% — 8A
53% — 87
52% — 85
51% — 82
50% — 80
49% — 7D
48% — 7A
47% — 78
46% — 75
45% — 73
44% — 70
43% — 6E
42% — 6B
41% — 69
40% — 66
39% — 63
38% — 61
37% — 5E
36% — 5C
35% — 59
34% — 57
33% — 54
32% — 52
31% — 4F
30% — 4D
29% — 4A
28% — 47
27% — 45
26% — 42
25% — 40
24% — 3D
23% — 3B
22% — 38
21% — 36
20% — 33
19% — 30
18% — 2E
17% — 2B
16% — 29
15% — 26
14% — 24
13% — 21
12% — 1F
11% — 1C
10% — 1A
9% — 17
8% — 14
7% — 12
6% — 0F
5% — 0D
以上是关于Android开发百科全书②的主要内容,如果未能解决你的问题,请参考以下文章

Android开发百科全书③

Android开发百科全书①

Python开发简单爬虫---爬取百度百科页面数据

转帖维基百科中的各国海军现役舰艇②:美国海军

Android开发游记:RecycleView 实现复杂首页布局三种方式

Android Socket通讯