android-《第一行代码》-第一章 正式启程&第二章 Activity(温故而知新)学习记录

温故而知新

这一点主要是在比较不忙的时间,巩固一下android的基础知识。

第一章 开始启程

  1. 在res目录文件关于mipmap中的多种文件,例如hdpi,xhdpi,xxhdpi等等不同类型的文件名。
    可以参考res中文件夹名的意义
    摘取其中的一些内容:
QHD     960*540
720p    1280*720  标清
1080p  1920*1080 高清
"QHD      hdpi "
"720P     xhdpi"
"1080P   xxhdpi "
  1. 在build.gradle 文件plugins的认识
plugins {
    id 'com.android.application'
}

plugins {
    id 'com.android.library'
}

两者对应的东西是不一样的:前者应用模块直接就可以运行,后者库模块需要依附应用模块。
3. android最大的闭包:以下我截取我之前项目中的一些配置代码并在上面做相应的解释

android {
    compileSdkVersion 30 // 编译版本 表示SDK的
    buildToolsVersion "30.0.2" // 构建工具的版本
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    packagingOptions {
        pickFirst 'META-INF/*'
    }

    defaultConfig {//默认配置
        applicationId "com.example.zegoimmultitest" // 包名,这是唯一的,前面构建项目的时候写了,修改的地方就是这里
        minSdkVersion 21 //最低兼容的版本
        targetSdkVersion 30 // 充分测试过的版本
        versionCode 1 // 该项目的版本号
        versionName "1.0" // 项目的版本名,这两个version在后面的生成安装文件中起到至关重要的
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
        }
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {//正式安装的版本,其中还有一个debug的,但是这个一般可忽略
            minifyEnabled false //代码混淆开启
        	//混淆的文件规则
		    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

下面是dependencies闭包,主要是对项目的第三方导入的依赖,例如本地依赖以及库依赖,远程依赖:

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0' // 远程依赖
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'com.google.android.material:material:1.3.0'
    implementation project(path:':Scenes')。//库依赖
    implementation project(path: ':CommonFeatures')
    implementation project(path: ':AdvancedVideoProcessing')
    implementation project(path:':AdvancedStreaming')
    implementation project(path: ':Quickstart')
    implementation project(path: ':Others')
    implementation project(path: ':DebugAndConfig')
    implementation project(path: ':AdvancedAudioProcessing')
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.tencent.bugly:crashreport:3.2.422'
    implementation 'com.tencent.bugly:nativecrashreport:3.7.500'
    implementation files('libs/ZegoExpressEngine.jar') // 本地依赖
}

第二章 探究活动

  1. 学习使用menu菜单;首先在res中构建一个menu然后在activity进行展示
  @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main,menu);
        return  true;
    }

选择好菜单之后,相应地需要对这些item进行监听实现相应的功能。这里就得使用到如下的代码进行设计:

@Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
     switch (item.getItemId()){
         case R.id.add_item:
             Toast.makeText(this,"add",Toast.LENGTH_SHORT).show();
             return true;
         case R.id.remove_item:
             Toast.makeText(this,"remove",Toast.LENGTH_SHORT).show();
             return true;
         default:
             return  true;
     }

  1. 销毁一个活动
    finish()方法即可实现。
  2. intent的使用
    这里主要是两个方向,第一是显式;第二是隐式;
    显式:
Intent intent = new Intent(this, SecondActivity.class);  
startActivity(intent);  
ComponentName componentName = new ComponentName(this, SecondActivity.class);  
// 或 ComponentName componentName = new ComponentName(this, "com.example.app.SecondActivity");  
// 或 ComponentName componentName = new ComponentName(this.getPackageName(), "com.example.app.SecondActivity");    
Intent intent = new Intent();  
intent.setComponent(componentName);  
startActivity(intent);
Intent intent = new Intent();    
intent.setClass(this, SecondActivity.class);  
// 或 intent.setClassName(this, "com.example.app.SecondActivity");  
// 或 intent.setClassName(this.getPackageName(),"com.example.app.SecondActivity");            

startActivity(intent);  

隐式比较含蓄:主要是使用如下的:

<activity  
    android:name="com.example.app.SecondActivity">  
    <intent-filter>  
        <action android:name="mark"/>  
        <category android:name="android.intent.category.DEFAULT"/>  //默认的一个category
    </intent-filter>  
</activity> 

其中的filter过滤器的作用比较重要点。
一个activity可以有多个category。
这部分,有些文章写的很好,可以参考!
其中有内置的一些可以调用的其他程序的活动,例如网页解析

// 打开百度主页
Uri uri = Uri.parse("https://www.baidu.com");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);

这样就直接跳转过去了。当然是在os中的浏览器中进行展现的。
Data:表示与动作要操纵的数据

一个URI对象是一个引用的data的表现形式,或是data的MIME类型;data的类型由Intent的action决定

  1. intent 的数据传递
    这里使用的intent.putExtra()方法可以将活动与活动之间的数据进行传递。而需要接受的数据的intent可以采用getXX()方法进行获取,其中的XX指的是特定的数据类型,数值的传递是通过kv对进行的匹配的。
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
                //数据通过putExtra()以键值对形式传递数据  use putExtra() by key-value transmit values
                intent.putExtra("hello",str);
                startActivity(intent);

那么返回数据给上一个活动应该采用什么的方法呢?

 Intent intent = new Intent(ActivityA.this, ActivityB.class);
                //第一个参数是intent,第二个参数是请求码,随便定义,保证是唯一的就行
                startActivityForResult(intent, 1);
//重点是在本活动activity中override如下的方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        //这里要通过请求码来判断数据的来源
        switch (requestCode) {
            case 1:
            //判断请求的结果是否成功,resultCode == RESULT_OK,代表成功了
                if (resultCode == RESULT_OK) {
                    String getData = data.getStringExtra("data");
                    Toast.makeText(ActivityA.this, getData, Toast.LENGTH_LONG).show();
                }
                break;
            /**这里可以有多个requestcode**/    
                default:
        }
    }

负责回传数据的活动需要setResult进行返回

Intent intent = new Intent();
                //将要传给activityA的数据存放在intent中
                intent.putExtra("data", "你好,time");
                //第一个参数用于向上一个活动返回结果,一般有RESULT_OK和RESULT_CANCEL两个值,第二个参数把带有数据的intent传回去
                setResult(RESULT_OK, intent);

小强调一下activity中存在onBackPresses()方法,该方法是用户点击返回键(os自带的)会触发的方法。这个回传数据的实现也可以在这个方法中进行实现。

返回栈——activity的关键之一

任务和返回栈是activity 中重要的概念,在这一部分可以参考谷歌开发者的介绍

任务是用户在执行某项工作时与之互动的一系列 Activity 的集合。这些 Activity 按照每个 Activity 打开的顺序排列在一个返回堆栈中。

您可以通过启动模式定义 Activity 的新实例如何与当前任务关联。您可以通过两种方式定义不同的启动模式:

  1. 使用清单文件

当您在清单文件中声明 Activity 时,您可以指定该 Activity 在启动时如何与任务关联。这个是我个人比较常用的一个方法。
在清单文件即manifest中可以将进行如下操作:

android:launchMode="singleInstance"
	android:launchMode="singleTask"
            android:launchMode="singleTop"
            android:launchMode="standard"
//一个activity只能对应这四个指定mode的一个

这四个模式的区别可以参考[开发者文档](https://developer.android.google.cn/guide/components/activities/tasks-and-back-stack#ManagingTasks )进行学习。

standard:默认值,在新的activity上再构建一个new的activity

singleTop:看中文大意即单例置顶;可以这样理解——例如,

假设任务的返回堆栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈为 A-B-C-D;D 位于顶部)。收到以 D 类型 Activity 为目标的 intent。如果 D 采用默认的 “standard” 启动模式,则会启动该类的新实例,并且堆栈将变为 A-B-C-D-D。但是,如果 D 的启动模式为 “singleTop”,则 D 的现有实例会通过 onNewIntent() 接收 intent,因为它位于堆栈顶部,堆栈仍为 A-B-C-D。但是,如果收到以 B 类型 Activity 为目标的 intent,则会在堆栈中添加 B 的新实例,即使其启动模式为 “singleTop” 也是如此。

singleTask:这一部分在官方文档上看的模棱两可,迷迷糊糊的。所以比较推荐其他的文章参考;主要的业务意思是:标记为singleTask的Activity,在启动的时候如果当前没有实例,就和standard模式一样,直接压栈到当前activity上;如果已经有实例了,就把该目标Activity实例上面的activity都清除,从而将目标Activity暴露到最上面,调用了其onNewIntent方法。

singleInstance:与 “singleTask” 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。


  1. 使用 Intent 标记
    这一部分的内容和知识点可以参考文章。这里主要是通过实际的业务逻辑对于intent下的activity的启动模式进行设计。

当您调用 startActivity() 时,可以在 Intent 中添加一个标记,用于声明新 Activity 如何(或是否)与当前任务相关联。
例如:

Intent it = new Intent(SecondActivity.this, SecondActivity.class);
it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(it);

activity的生命周期

这一个知识点基本上只要面试android的工作岗位基本上都会过一遍的。可以说是安卓开发的“九九乘法表”!这个知识点郭大神已经讲的比较清晰了,当然,这种东西自己再去官网专门针对activity的生命周期的文章读一遍更佳。

  1. 生命周期详见此图
  2. 阅读官方文档的时候,关于onPause的部分我觉得讲得很不错,故特将其copy过来。

Activity 进入此状态的原因有很多。例如:
如 onResume() 部分所述,某个事件会中断应用执行。这是最常见的情况。在 Android 7.0(API 级别 24)或更高版本中,有多个应用在多窗口模式下运行。无论何时,都只有一个应用(窗口)可以拥有焦点,因此系统会暂停所有其他应用。有新的半透明 Activity(例如对话框)处于开启状态。只要 Activity 仍然部分可见但并未处于焦点之中,它便会一直暂停。

同时,在这个activity的生命周期的时刻,这里是不利于储存数据的时间节点,因为时间不一定足够。

onPause() 执行非常简单,而且不一定要有足够的时间来执行保存操作。因此,您不应使用 onPause() 来保存应用或用户数据、进行网络调用或执行数据库事务。

巧用方法,提高认识和开发activity的能力

  1. 确定activity的位置
    在开发过程中因为activity的类型多,且不知道运行的是哪一个activity,虽然可以进行debug进行判断。但是这里提供一个新的思路,使用父类的思想。
    例如:构建一个myActivity类继承父类在onCreate中log日志打印当前的类名。然后所有的activity都可以继承这个类,这个也不影响整体的代码逻辑。
public class BaseActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
        //我们在onCreate()方法中获取了当前实例的类名,并通过Log 打印了出来。
    }

  1. 直接退出整个程序
    首先构造一个工具类
public class ActivityCollector {
    public static List<Activity> activities = new ArrayList<>();

    public static void addActivity(Activity activity){
        activities.add(activity);
    }

    public static void removeActivity(Activity activity) {
        activities.remove(activity);
    }

    public static void finishyAll(){
        for(Activity activity:activities){  // 遍历
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
        activities.clear();
    }
}

在上面所示的BaseActivity中进行改写,每一个活动都继承这个BaseActivity对象即可。在通过一些业务逻辑或者组件触发这个finishAll方法即可

public class BaseActivity extends AppCompatActivity{
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity", getClass().getSimpleName());
        ActivityCollector.addActivity(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityCollector.removeActivity(this);
    }
}
  1. 最佳启动activity的方式
    主要是通过静态方法进行活动的启动
 public static void actionStart(Context context, String account, String password){
        Intent intent = new Intent(context,FirstActivity.class);
        intent.putExtra("account",account);
        intent.putExtra("password",password);
        context.startActivity(intent);
    }

以上的参数可以自己进行修改,主要的context这个对象是不能缺少的!接着在相关的地方进行调用这个静态方法即可!

 FirstActivity.actionStart(MainActivity.this,account,password);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值