Android从入门到入坟(一)

1、活动的创建

通过 新建项目选择No Activity 从而手动创建活动

通过在java包中的 com.example.activity test 中右击新建一个Activity再选择想要的模块创建即可

Generate Layout File 表示创建一个对应的布局文件

Launcher Activity 表示设置当前活动为主活动

在新的版本中已经回自动生成 对应的layout.xml可视化文件了

在活动的方法中通过 " setContenView(R.layout.Activityfirts) " 与对应的layout.xml文件绑定

setContenView(R.layout.FirstActivity)

2、Android Manifest 活动注册

每当我们生成了一个Activity活动 系统都会自动帮助我们在其中注册

在系统注册的活动标签中使用了Android:name 用来指定具体所注册的活动

然后还需要再其中加上标签 并在标前中添加两句声明才可以正常使用,如下

<action android:name="android.intent.action.Main"/>
<category android:name="android.intent.category.LAUNCHER"/>

这两句声明用来指定首先启动的活动

并且可用使用 Android:lable=“” 用来指定活动标题

修改后的整体代码如下:

<activity
    android:name=".firstActivity"
    android:lable="this is FirstActivity">
	<intent-filter>
    	<action android:name="andro.intent.action.MAIN"/>
        <categoty android:name="android.intent.categoty.LAUNCHER">
    </intent-filter>
</activity>

3、Toast 提示

相当于 JavaScript 中

使用Toast时需要定义一个触发器 可以使用 button 控件生成触发事件

我们使用 用来获取局部文件中定义的元素 通过传入<R.id.button_1>从而获取控件实例;代码如下

Button btn=findViewById(R.id.Button_1)

再通过 setOnClickListener() 方法注册监听器注册之后 会自动生成一个 OnCilick 的点击方法 代码如下

btn_setOnClickListener(new View.OnClickListener(){
	@Override
	publick void onClick(View view){
		
	}
});

Toast 使用比较简单 通过 makeText()创建一个Toast对象 再通过Show() 打开方法便可 ,

注意:makeText()方法需要传入三参数

1、第一个参数需要传入一个Context,而Activity 本身就是一个Context 象 所以直接使用FirstActivity.this即可;

2、第二个参数则是需要显示的字符串

3、第三参数则定义显示的弹出的时间长度有两个内置常量用于选择

常量一、LENGTH_LONG(length_long)

常量二、LENGTH_SHORT(length_short)

完整代码

Button btn=findViewById(R.id.button_1);

btn=setOnClickListener(new View.OnClickListener(){
	public void onclick(View view){
		Toast.makeText(FirstActivity.this,"Hello Word",LENGTH_SHORT).show();
	}
});

4、Menu 菜单

使用Menu 菜单 时 首先再res 文件夹下创建一个 menu 文件夹

其次再在menu 文件夹通过 Menu Resource File 创建一个 main 的菜单文件

然后通过 创建一个具体的菜单项

通过 Android:id 创建一个具体的标识符号

通过 Adroid:title给菜单指定名称

代码如下

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
  	<item 
    	 android:id="@id/add_item"
         android:title="ADD"/>
    <item
         android:id="@id/remove_item"
         android:title="Remove"/>
</menu>

然后返回 FirstActivity 中重写onCreateOptionMenu() 方法 使用快捷键 Ctrl+O 可以快速重写

然后 我们通过 getMenuInflater() 方法 得到 MenuInfalater对象

再调用 inflate() 方法给当前活动创建菜单

inflate() 方法需要传入两个参数

参数一、用于指定通过哪个资源文件来创建菜单 R.menu,main

参数二、指定菜单添加到哪个自定对象中

如果 onCreateOptionMenu()方法中返回 true 表示允许显示菜单 否则反之

代码如下:

public boolean onCreateOptionMenu(Menu menu){
    getMenuInflater().inflate(R.Menu.main,menu);
    return true;
}

现在只是创建出菜单了 而我们还需要为其定义事件

因此我们还需要重写 onOptionsItemSelected() 方法

依旧 使用快捷键Ctrl+O找到需要重写的方法

再通过 < item.getItemId() > 方法用来获取menu 对象 再通过Switch 获取到对应的menu 对象

代码如下:

// 首先重写Menu响应方法
public boolean setOptionItemSelected(@NonNull MenuItem item){
    swich(item.getItemId()){
        case R.id.add_item:
        	Toast.makeText(this,"You Checkd Add",LENGTH_SHORT).show();
        	break;
        case R,id.Remove_item:
        	Toast.makeText(this,"You Check Remove",LENGTH_SHORT).show();
        	break;
        default:
        	break;
    }
    return true;
}

5、finish 活动销毁

销毁一个Activity活动只需要按一下Back 键即可

如果想要通过代码的方式进行销毁 可以使用 Activity 中所提供的 方法进行销毁

代码如下:

// 获取控件
Button btn =findViewById(R.id.Button_ID)
btn.setOnClickListener=(new View.OnClickListener(){
    public void onclick (View View){
        finish();
    }
});

6、Intent 活动穿梭

1、显式Intent

Intent 有多个重载的构造函数

构造一:Intent(Context packageContext,Class<?> cls)

这个构造函数接收两个参数

参数一:Context: 要求提供一个启动活动的上下文

参数二:Class: 要求提供 一个想要启动的活动

构造一的使用:

在Activity中提供了 startActivity() 的方法用于专门启动活动

他需要接受一个Intent参数,因此我们只需讲构建好的Intent参数 传入其中就好了

代码如下:

// 构建Intent
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
// 传值
StartActivity(intent);
2、隐式Intent

相比较显示Intent,隐式Intent 则含蓄了更多 他不明确指出需要启动的活动

而是指定了一系列更加抽象的action 和 categoty等信息

然后再通过系统去分析 Intent 从而找出适合的活动去启动

因此我们在 AndroidManifest.xml文件下 为指定活动添加如下代码

<activity androuid:name=".SecondActivity">
	<intent-filter>
    	<action android:name="com.example.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
    
</activity>

action中的代码指定了当前活动可以响应com.example.activitytest.ACTION_START这个action

而category标签则包含了一些附加信息,只有两者匹配时才可以响应

我们回到中 修改按钮跳转信息

public void OnClick(View view){
    Intent intent=new Intenr("com.example.activitytest.ACTION_START");
    StartActivity(intent);
}

因为我们category 中 设置的是 <android.intent.category.DEFAULT > 这是一种默认的categoty

在我们使用 StartActivity 时会自动添加该条属性

在每条Intent中只能指定一条action 但是可以指定多条 category

public void OnClick(View view){
    Intent intent=new Intenr("com.example.activitytest.ACTION_START");
    intent.category("com.example.activitytest.MY_ACTIVITY")
    StartActivity(intent);
}

然后我们再向AndroidManifest.xml中给相应的Activity的标签中添加一条category声明

<activity androuid:name=".SecondActivity">
	<intent-filter>
    	<action android:name="com.example.activitytest.ACTION_START"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="com.example.activitytest.MY_ACTIVITY"/>
    
</activity>
3、更多隐式Intent的用法

使用隐式Intent来启动其他程序的活动比如打开百度 我们只需要调用系统的浏览器来打开这个网页即可

我们首先指定intent 的是Intent.ACTION_VIEW 这是一个android 系统内置的动作

其常量为 android:intent:action.View

然后 再通过 Uri.parse() 方法讲传入的网址字符串解析成一个Uri 对象

再调用 Intent 的setData() 方法 将这个Uri对象传递进去

代码如下

public void OnClick(View view){
    Intent intent=new Intent(Intent.ACTION.VIEW);
    // 解析网址字符串
    intent.setdata=(Uri.parse("http://www.baidu.com"));
    StartActivity(intent)
}

与此对应 我们可以再标签中配置一个标签用于更加精确的指定所能够响应声明什么类型的数据标签配置如下

Android:scheme:用于指定数据的协议部分

Android:host:指定数据的主机名部分 例如 www.baidu.com

Android:port:用于指定数据的端口部分。

Android:mimeType:用于指定可以处理的数据类型

除了使用http协议之外 还可以使用其他协议、

例如:

使用geo 显示地理位置

使用tel 表示拨打电话

public void setData_onclick_2(View view) {
       Intent intent=new Intent(Intent.ACTION_VIEW);
       intent.setData(Uri.parse("tel:10086"));
       startActivity(intent);
   }

7、向下一个活动传递数据

Intent 不仅可以用来启动活动 并且可以在启动活动时进行传递参数

在 Intent 中提供了一系列的 putExtra()方法的重载 可以暂时将数据存储在Intent 中

启动另外一个活动之后只需要将intent 中的数据取出来即可

注意一个 putExtra()需要传入两个参数 一个是键 一个是值

储存数据代码如下:

public void OnClick(View view){
    EdiText name=findViewById(R.id.user_name);
    EdiText pwd=findViewById(R.id.user_pwd);
    String user_name=name.getText().toString();
    String user_pwd=name.getText().toString();
    
    // 构建 Intent
    Intent intent=new Intent(this,UserActivity.class);
    intent.putExtra("user_name",user_name)
        .putExtra("user_pwd",user_pwd);
    startActivity(intent);
}

取出代码如下:

取出传输的值时通过getStringExtra()方法取值 其中参数为值的键

public void pring(){
    // 获取值
    Intent intent=getIntent();
    String user_name=intent.getStringExtra("user_name");
    String user_pwd=intent.getStringExtra("user_pwd");
}

注意:

每种取值的方法都不一样

Int: getIntExtra()

String: getStringExtra()

Boolean: getBooleanExtra()

以此类推

8、向上传递数据

向上一个活动返回数据 我们通过startActivityForResult()该方法实现

startActivityForResult()方法需要传递两个参数

第一个参数:Intent

第二个参数:请求码——唯一值,用于判断数据来源

代码如下

public void OnClick(View view){
    Intent intent =new Intent(this,SecondActivity)
    startActivityForResult(intent,1001) 
}

该方法用去启动SecondActivity

实现之后我们再向SecondActivity 中加入返回数据的逻辑即可

代码如下:

public void OnClick(View view){
    // 构建 Intent 
    Intent intent =new Intent();
    intent.putExtra("Hello","Hello Word");
    setResult(RESULT_OK,intent);
    finish();
}

在其中我们构建了Intent只用于传值 然后使用putExtra() 方法传入需要的数据

再通过 专门用于向上传值的方法setResult() 从而实现 传值

然后销毁该活动 , 现在 我们已经完成了传值的动作

只需回到SecondActivity中取出即可

因为我们使用的是 startActivityForResult() 因此销毁SecondActivity活动之后会自动回调onActivityResult方法,因此我们重写该方法即可

代码如下:

@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 1001:
                if (resultCode == RESULT_OK) {
                    String str = data.getStringExtra("hello");
                    Log.v(TAG, str);
                }
                break;
            default:
                break;
        }
    }

但是如果用户通过Back键 从而返回到上一个活动未触发返回的点击事件则无法返回值

因此我们还需要重写onBackPressed()方法进行返回即可

代码如下

@Override
public void OnBackPressed(){
    Intent intent=new Intent();
    intent.putExtra("Hello","Hello Word!");
    // 依旧通过 setResult()方法返回会
    setResult(RESULT_OK,intent);
    finish()
}

9、活动的生命周期

1、返回栈

在前面的学习中可以方向 Android 中的活动是可以层叠的我们通过back键 可以销毁上面的活动

显示新的活动

其实我们可以通过 任务(Task)从而管理活动 一个任务就是一组存放在栈中的活动集合

这个栈也被成为 返回栈( Back Stack ) 栈是一种后进先出的结构

每当完美启动了一个新的活动 他就会返回栈中 处于栈顶的位置

每当我们销毁一个栈时处于栈顶的活动就会出栈

2、活动状态

每个活动在其生命周期中最多可能会有四种状态

1、运行状态

当一个活动位于返回栈的栈顶时,这个活动就处于运行状态

2、暂停状态

当一个活动不在处于栈顶位置,但仍然可见时 这个活动就进入了暂停状态

例如处于对话框形式的活动只会占用屏幕的中间部分区域

你仍然可看见后面的活动 这种活动仍然是活着的存在

3、停止状态

当一个活动不再处于栈顶,并且完全不可见时,就进入了停止状态

系统仍然会为这种活动保存相应的状态和成员变量

4、销毁状态

当一个活动从返回栈中移除后就变成了销毁状态

3、活动的生存期

在Activity 中定义了7个回调方法 覆盖了活动生命周期的每一个环节

1、onCreate()

在该方法中完成活动的初始化操作 比如加载布局,绑定事件等

2、onStart()

这个方法在活动由不可见变成可见的时候调用

3、onResume()

这个方法在活动准备好和用户进行交互的时候调用,此时的活动一定位于

返回栈的顶部并且处于运行状态

4、onPause()

这个方法在系统准备去启动或者恢复另外一个活动的时候调用

5、onStop();

这个方法在活动完全不可见时进行调用,入伙新的活动是一个对话框式的活动

那么onPause()方法会得到执行 而不是onStop()方法

6、onDestroy()

这个方法在活动被销毁的之前调用 之后活动将变成销毁状态

7、onRestart()

这个和方法在活动由停止状态变成运行状态之前调用,也就是活动被重新启动时

在这些活动中 除了onRestart()方法 其他都是两两相对
1、完整生存期:

活动在onCreate()方法和onDestory()方法之间所经历的

一般在onCreate()方法中完成初始化,在onDestory()方法中释放资源

2、可见生存期

活动在onStart()和onStop()中所经历的就是可见生存期

在可见生存期中,活动对于用户总是可见的,即使无法和用户交互

我们通过这两个方法可以合理管理用户可见的资源,从而保证停止状态的霍东阁

不会过多占用内存

3、前台生存期

活动在onResume()和onPause()方法中所经历的就是前台生存期

活动处于运行状态,并且可以和用户进行交互的就是前台生存期

启动活动
onCreate
onStart
onResurme
活动运行中
活动来到前台
onPause
活动不在可见
onStop
活动被销毁
OnDestory
关闭活动
返回上一个活动
onRestart
另一个优先级更搞的成勋需要内存
另一个优先级更高的程序需要内存

10、体验活动周期

首先重新建立一个项目在新建两个活动【Normal-Activity】【Dialog-Activity】

进行简单的布局之后

我们进入AndroidManifes.xml 文件中进行配置,将DialogActivity活动 设置成一个提示窗口模式

<activity
    android:name=".DialogActivity"
    android:theme="@style/Theme.AppCompat.Dialog"/>

然后 我们们分别向新建的mainActivity 中 分别向两个活动添加跳转代码

然后重写七个回调方法 在每一条中分别打印,代码如下

@Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: 被触发了");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: 被触发了");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart: 被触发了");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: 被触发了");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: 被触发了");
    }
    

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: 被触发了");
    }

    private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: 被触发了");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 注册监听器
        Button btn_normal=findViewById(R.id.Button_Normal);
        Button btn_dialog=findViewById(R.id.Button_Dialog);
        btn_normal.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                构建 intent 传递给 startAcitvity 启动其他活动
                Intent intent=new Intent(MainActivity.this,NormalActivity.class);
                startActivity(intent);
            }
        });
        btn_dialog.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent=new Intent(MainActivity.this,DialogActivity.class);
                startActivity(intent);
            }
        });
        
    }

11、活动回收,数据保存

如果一个活动进入停止状态后 被系统回收,用户又重新回到该页面 系统则会重新执行 onCreate方法重新初始化该活动 但是 活动中本存在的临时数据不会得到加载

因此Activity提供了【onSaveInstanceState】这个方法可以保证在活动被回收之前一定会被调用,因此我们可以通过这个方法来解决活动回收时数据得不到保存的问题

在【onSaveInstanceState】方法中会携带一个【Bundle】类型的参数,【Bundle】中提供了一系列的方法用于保存数据例如 【putString 】保存字符串,【putInt】保存int类型等等 以此类推

每个保存方法都需要传入两个参数

1、第一个参数为用于取值的键

2、第二个参数则是真正的保存值

代码如下

@Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("key","Hello Word!");
    }

现在的数据哪怕活动被销毁也会得以保存

我们我们现在只需要在初始化活动时将内容取出来即可

我们会发现 在初始化活动方法onCreate中也存在一个 Bundle 的参数

我们通过getString将其取出即可

 protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate: 被触发了");
        super.onCreate(savedInstanceState);

        if (savedInstanceState!=null){
            String str=savedInstanceState.getString("key");
            Log.d(TAG, str);
        }
 }

12、活动的启动模式

在实际的项目中我们应该根据特定的需求为每一个活动指定恰当的启动模式

启动模式一个共分成四种【standard】【singleTop】【singleTask】【singleInstance】

1、standard

standard时活动中默认的启动模式,每当创建一个standard模式的活动,它都会在返回栈中入栈,并且处于栈顶的位置,如果活动本身正处于栈顶,新建一个本身的实例后

表面没什么区别 ,而此时返回栈中已经存在了两个相同的活动

因此你需要点击两次back键才可以退出程序

2、singleTop

而singleTop启动模式能够非常有效的解决重复创建栈顶的活动的问题

通过singleTop创建模式启动活动时如果发现返回栈的栈顶已经时该活动了则会直接使用他

而不是再重新创建新的活动实例

我们只需修改AndroidManifest.xml文件中activity>属性的Launch Mode属性即可

代码如下

<activity
	android:name=".FirtsActivity"
	android:exported="true"
	android:label="this FirstActivity
	android:launchMode="singleTop">
	<intent-filter>
       	<action android:name="android.intent.action.MAIN" />
       	<category android:name="android.intent.category.LAUNCHER" />
   	</intent-filter>
</activity>

但是缺点也非常明显

如果你从FirstActivity页面中跳转到SecondActivity活动中在从中创建一个FirstActivity则singletop模式检测到的栈顶是SecondActivity 所以他又会重新创建一个新的FirstActivity

但是Acvtivity中还提供了一种名为singleTask的启动方法 能够非常有效的解决这种问题

3、singleTask

每当我们通过singleTask创建模式启动了一个新的活动 ,可能新的活动之前已经启动过了

并没有处于栈顶的位置,我们的系统会每次都对我们的返回栈进行一个检查

如果在返回栈中存在 那么将会通过onStart方法重新启动该活动,而不是创建新的实例

如果没有发现则会创建新的活动

代码如下

<activity
	android:name=".FirtsActivity"
	android:exported="true"
	android:label="this FirstActivity
	android:launchMode="singleTask">
	<intent-filter>
       	<action android:name="android.intent.action.MAIN" />
       	<category android:name="android.intent.category.LAUNCHER" />
   	</intent-filter>
</activity>
4、SingleInstance

这个模式非常有效的处理了多个程序的互相调用,如果使用【SingleInStance】启动模式创建活动

那么他将会当初生成一个返回栈用来存放启动的活动

因此不管是从什么应用程序下访问的这个活动 都是共用的一个返回栈

也就解决了共享活动的实例问题

通过实操可以知道 通过 SingleInstance所启动的活动每次都会生成一个新的单独的返回栈

13、活动的最佳管理方式

1、活动管理

如果我们接手他人的项目,想要快速熟悉项目 知道启动的窗口是什么

我们可以新建一个BaseActivity的普通Class类并且使其继承AppCompatActivity

然后再BaseActivity中重写onCreate方法 并在其中通过getClass().getSimpleName()的方法获取初始化实例的类名并打印出来

然后在修改其他活动的继承类 将其一 一改成BaseActivity

于是其他类不仅能够继承AppCompatActivity也能执行BaseActivity中的方法

代码如下

public class BaseActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity",getClass().getSimpleName());
    }
}
2、活动的正确销毁姿势

根据之前的案例我们会发现如果想快速退出程序还需要按三次Back键

而我们如果想要快速的退出一个程序则需要一个专门的集合

这个集合用来管理所有的活动

我们新建一个名为ActivityCollector的普通java类

其中代码如下

public class ActivityCollector{
    // 创建一个list集合用于管理所有的活动
    public static ArrayList<Activity>Activity_List=new ArrayList<>();
    活动的添加
    public void AddActivity(Activity activity){
        Activity_List.add(activity)
    }
    当前活动的销毁
    public void RemoveActivity(Activity activity){
        Activity_List.Remove(activity)
    }
    整个程序的销毁
    public void finishActivity(){
        for(Activity activity:Activity_List){
            if(!activity.isFinishing()){
                activity.finish();
            }
        }
    }
}

然后我们再前往BaseActivity中添加对应代码

public class BaseActivity extends AppCompatActivity {

    public  static  ActivityCollector activityCollector=new ActivityCollector();
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("BaseActivity======",getClass().getSimpleName());
        activityCollector.AddActivit(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        activityCollector.RemoveActivity(this);

    }
}

在BaseActivity类中我们重写了OnDestory()这个方法

这个方法是活动周期的七个回调方法之一用于在销毁活动之前进行调用

我们在其中加上了ActivityCollector类中的删除方法RemoveActivity方法

确保添加和删除是一致的

然后我们在重写的初始房啊OnCreate方法中添加了把活动添加到集合中的方法

如果我们想要关闭整个程序

我们可以直接调用

finishiActivity()方法则可以直接关闭整个程序

第二章结束

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值