基于《第一行代码》Activity学习

1.当默认创建一个新项目时,开发工具会帮我们创建一个MainActivity.java,以下是用AndroidStudio来创建的部分代码,MainActivity.java的主要代码(每个人的开发工具不尽相同,在新建项目时可能会同时生成多几个方法,这时可以忽略掉它们,因为这不影响研究)
public class MainActivity extends AppCompatActivity {   
   @Override    
  protected void onCreate(Bundle savedInstanceState) {  
      super.onCreate(savedInstanceState);    
      setContentView(R.layout.activity_main);    
  }
}
2.创建和加载新的布局文件

创建新的布局文件这一步可以自己创建一下,我自己创建的一个新的布局文件名为 activity_second.xml。
布局文件创建好之后,再创建一个新的Activity来加载activity_second.xml,这里我创建的Activity名为Activity_second。代码如下:

public class Activity_second extends AppCompatActivity{  //1
    @Override                                            //2
    protected void onCreate(Bundle savedInstanceState) { //3       
        super.onCreate(savedInstanceState);              //4
    }
}

此时新鲜滚热辣的Activity_second.java还未将刚才创建的activity_second.xml加载进去呢!此时我们应该做的就是在上面的标号为4的此行代码后面进行加载布局文件,使用setContentView( )方法进行加载布局文件。

public class Activity_second extends AppCompatActivity{  //1
    @Override                                            //2
    protected void onCreate(Bundle savedInstanceState) { //3       
        super.onCreate(savedInstanceState);              //4
        setContentView(R.layout.activity_second);//这一步操作就是加载布局文件啦!!
    }
}
3.在AndroidManifest.xml清单文件中对Activity_second进行注册操作


    
        
            
                                
                            
            
        
                
                
        
    

4.在代码中销毁一个Activity

调用finish( )方法即可以销毁当前的Activity。我下面的代码是事先在activity_main.xml中定义了一个Button,并设置该Button的onClick属性为finishActivity。所以在MainActivity中就可以将该Button的onClick属性声明为一个方法用于销毁当前的Activity了。代码如下:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void finishActivity(View view){
        finish();
    }
}

Activity的交互


5.使用Intent(意图)来连通各个Activity

首先,Activity之间交互是通过(意图)Intent来进行的,所以我们应该先要将这个(意图)Intent构建出来,然后将这个(意图)Intent作为参数传入startActivity(intent)方法即可实现Activity之间的交互。
  Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务、以及发送广播等场景。
--5.1多个Activity使用显式Intent来进行交互
Intent有多个构造函数的重载,最常用到的是:Intent(Context packageContext, Class cls)。

Intent intent = new Intent(MainActivity.this,Activity_second.class);
startActivity(intent);

我们首先是构建出了一个意图Intent,将MainActivity.this作为上下文,传入Activity_second.class作为目标活动。这个Intent的意图(目的)就是在MainActivity这个活动的基础上打开Activity_second这个活动。最后,通过调用startActivity( )方法来执行这个Intent意图。这种意图比较明显,所以称之为显式Intent。
--5.2单应用中的多个Activity使用隐式Intent进行交互
  隐式Intent就是先找到AndroidManifest.xml清单文件中的要跳转到的目标Activity注册处,然后在该处添加一个意图过滤器,在这个意图过滤器中指定action和category等信息。最后交由系统去分析这个Intent并帮我们找出合适的Activity去启动。
主要的清单文件代码如下:


    
        
        
    

在调用方MainActivity中的主要代码如下:

Intent intent = new Intent("com.example.andre.testactivityapplication.ACTION_START");
startActivity(intent);

可以看出这里调用了Intent的另一个构造方法,并将一个在清单里面注册的一个action字段作为参数,然后再调用startActivity( )方法跳转到Activity_second中去。
注意:这里看似调用Intent的构造方法时漏掉了清单文件中提及的另外一个category字段,其实这个category字段是系统默认的字段,在调用startActivity( )方法时会自动将这个category字段添加到Intent中的。还有:每个Intent中只能指定一个action字段,但可以指定多个category字段,使用Intent的addCategory( )方法来指定多个category字段,但无论是在清单文件中新增category字段,还是在Activity中增加category字段,都一定要在彼此间进行category字段的全部匹配,除外。
--5.3更多的隐式Intent的用法
  使用隐式Intent不单单可以启动本程序内部的Activity,还可以启动其它程序的Activity。比如说你的程序想要打开网页时,只需要调用系统的浏览器来打开网页就可以了,没必要自己去做一个浏览器出来。下面就来看看在自己程序中如何打开浏览器并且访问百度首页的。

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("http://www.baidu.com");
intent.setData(uri);
startActivity(intent);
6.Activity之间的数据传递

--6.1向下一个Activity传递数据
  在当前的Activity向下一个Activity传递数据,使用的依然是Intent,因为Intent提供了很多的putExtra( )方法的重载,可以重载此方法将想要传递的一些数据加载到Intent中,然后在目标Activity中使用getIntent( )方法来获取上一个传数据进来的Activity中的Intent,最后调用获取到的Intent中的getxxx( )来将砸破Intent中的数据取出来,这样就完成了向下一个Activity传递数据啦。
  当前Activity中的主要代码:

String datas = "hello world!";
Intent intent = new Intent(this, Activity_second.class);//使用显式的Intent方式来启动Activity_second
intent.putExtra("pass_datas",datas);
startActivity(intent);

需要接收数据的目标Activity的主要代码:

Intent intent = getIntent();
String getPassDatas = intent.getStringExtra("pass_datas");

--6.2将数据返回给上一个Activity
  (这小点里面讨论的Activity的启动模式皆为标准模式)讨论的是两种情形,情景一:当前MainActivity通过按键来启动Activity_second,Activity_second启动完毕之后再调用finish( )方法将自己结束掉,然后就回到了MainActivity;情景二:在启动了Activity_second之后,通过返回键来返回MainActivity。
  情景一(自行设置点击事件):
  MainActivity中的主要代码如下:

Intent intent = new Intent(this, Activity_second.class);//使用显式的Intent方式来启动Activity_second
startActivityForResult(intent,1);//参数1为该请求码,这里传入1就可以了,也可以传其它值

Activity_second中的主要代码如下:

Intent intent = new Intent();//这个Intent是用来传数据的,并没有启动Activity的意图
intent.putExtra("return_datas","Datas return to MainActivity!");
setResult(RESULT_OK,intent);
finish();

Activity_second中的代码setResult(RESULT_OK,intent);这个方法专门用于向上一个Activity返回数据的,这方法里的第一个参数表示向上一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED这两个值,第二个参数是将带有数据的Intent传递回去,最后调用finish( )方法将自己销毁掉返回到MainActivity中。
  由于在MainActivity中是调用了startActivityForResult( )方法来启动Activity_second的,所以在Activity_second被销毁之后会回调MainActivity中的onActivityResult()方法,所以还要在onActivityResult()方法中进行相应的处理,具体如下:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode){
        case 1:
            String datas = data.getStringExtra("return_datas");
            break;
        default:
    }
}

onActivityResult(int requestCode, int resultCode, Intent data)方法中带有三个参数,第一参数requestCode即在MainActivity中启动Activity_second时手动设置的请求码,第二个参数resultCode即为Activity_second返回数据时传入的处理结果,第三个参数data是一个携带数据的Intent。由于在一个Activity中有可能会调用startActivityForResult()方法来启动很多个Activity,所以要用requestCode请求码来区分当前Activity是启动了哪个Activity,然后通过resultCode来判断处理结果是否成功,最后从data中将数据取出来,这样就完成了情景一的工作了。
  情景二:
  在Activity_second的时候直接按返回键时,这时情景一里面Activity_second的点击事件就无效了,其实可以通过重写onBackPressed( )方法来解决这个问题的,代码如下:

@Overridepublic void onBackPressed() {
    super.onBackPressed();
    Intent intent = new Intent();//这个Intent是用来传数据的,并没有启动Activity的意图
    intent.putExtra("return_datas","Datas return to MainActivity!");
    setResult(RESULT_OK,intent);
}

看到没,onBackPressed()方法里面的逻辑是从情景一中copy过来的,最后在MainActivity中的代码跟情景一是一样的,这样就可以在该情景中实现数据返回上一个Activity了。

Activity的生命周期与启动模式


7.Activity的生命周期
基于《第一行代码》Activity学习_第1张图片

  以上是Android官方的Activity生命周期回调图,各个方法功能如下:
  onCreate:初始化;
  onStart:开始activity,界面可见时调用这个方法;
  onResume:获得界面焦点;
  onPause:失去界面焦点;
  onStop:界面不可见;
  onRestart:重新开始打开一个界面,注意,重新打开的界面要处于未被销毁状态;
  onDestroy:在销毁实例对象之前调用这个方法;

Resumed:在这个状态, activity是在最前端的, 用户可以与它进行交互。 (通常也被理解为"running" 状态)
Paused:在这个状态, activity被另外一个activity所遮盖:另外的activity来到最前面, 但是半透明的, 不会覆盖整个屏幕。 被暂停的activity不会再接受用户的输入且不会执行任何代码。 (这里的不会执行任何代码并不代表了任何后台线程都不会工作)
Stopped:在这个状态, activity完全被隐藏, 不被用户可见。 可以认为是在后台。 当stopped, activity实例与它的所有状态信息都会被保留, 但是activity不能执行任何代码。
其它状态 (CreatedStarted)都是短暂的, 系统快速的执行那些回调函数并通过执行下一阶段的回调函数移动到下一个状态。 也就是说, 在系统调用onCreate(), 之后会迅速调用onStart(), 之后再迅速执行onResume()。
上面就是基本的Activity生命周期。

8.Activity的启动模式
   注:该小点所用到的图片皆为郭霖的《第一行代码》里面的截图进行修改。

Activity是使用返回栈来管理Activity的,其中Activity有4种启动模式:standard;singleTop;singleTask;singleInstance。启动模式是在清单文件中进行设置的,其中standard模式是默认的启动模式,可以不用在清单文件中进行添加字段。

--8.1standard模式
  在MainActivity中的点击事件里面加入下面代码:

Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);

然后点击2次这个点击事件的按钮,此时的返回栈如下图所示,需要连按3次返回键才能退出程序。


基于《第一行代码》Activity学习_第2张图片

--8.2singleTop模式

在此模式下当启动Activity时,如果发现返回栈的栈顶已经是该Activity时,则直接使用它,不会再创建新的Activity;当该返回栈中存在该Activity时,但它并不在栈顶,此时是会重新创建该Activity的。
  这种启动模式需要到清单文件中进行添加launchMode字段,xml代码如下:


    
        
        
    

在MainActivity中启动Activity_second,代码如下:

Intent intent = new Intent(MainActivity.this, Activity_second.class);
startActivity(intent);

接着在Activity_second中启动MainActivity,代码如下:

Intent intent = new Intent(Activity_second.this, MainActivity.class);
startActivity(intent);

在这种模式下,当你在Activity_second的点击按钮中点击了无数次,都只会有一个MainActivity在返回栈的栈顶,此时按下2次返回键就又回到了MainActivity界面中,再按1次就可以退出该程序,如下图:


基于《第一行代码》Activity学习_第3张图片

--8.3singleTask模式
  在此模式下,每次启动Activity时系统首先会在返回栈中检查是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并且把在这个Activity之上的所有Activity全部出栈,如果没有就会创建一个新的Activity实例。
  这种启动模式需要到清单文件中进行添加launchMode字段,xml代码如下:


    
        
        
    

重新运行程序,在MainActivity界面点击按钮进入到Activity_second,然后在Activity_second界面点击按钮,又会重新进入到MainActivity。
  返回栈流程如下:


基于《第一行代码》Activity学习_第4张图片

--8.4
  此模式可以解决共享Activity实例的问题,因为每个应用程序都会有自己的返回栈,同一个Activity在不同的返回栈中入栈时必然是创建了新的实例。而使用singleInstane模式时,会有一个单独的返回栈来管理这个Activity,从而实现共享Activity实例。
  将Activity_second添加launchMode字段,xml代码如下:


    
        
        
    

首先创建了Activity_third并在清单文件中进行注册

public class Activity_third extends AppCompatActivity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_third);
    }
}

然后修改修改Activity_second中的点击事件

Intent intent = new Intent(Activity_second.this, Activity_third.class);
startActivity(intent);

重新运行程序,在MainActivity界面点击按钮进入到Activity_second,然后在Activity_second界面点击按钮进入到Activity_third。当按下返回键进行返回时,发现Activity_third竟然直接返回到MainActivity,再按下返回键又会返回到Activity_second,再按一次返回键都会退出程序。
  原理是这样的,由于MainActivity和Activity_third是在同一个返回栈里的,当在Activity_third界面中按下返回键,Activity_third就会被出栈,此时MainActivity就处于栈顶了从而显示出来(也就出现了从Activity_third直接返回到MainActivity的情况),当再次按下返回键时,MainActivity就会被出栈,此时当前的返回栈已经空了,于是就显示了另一个返回栈的栈顶Activity,即Activity_second。最后再次按下返回键,所有的返回栈都已经空了,也就 退出了程序。返回栈流程如下:


基于《第一行代码》Activity学习_第5张图片

你可能感兴趣的:(基于《第一行代码》Activity学习)