• Android 基础(二)四大组件之Activity的基本运用


    一、Activity的基本使用

    Activity是一种可以包含用户界面的组件,主要用于与用户交互。

    创建

    创建Activity:new->activity->empty activity

    勾选Launcher Activity 表示会设为当前项目的主活动

    创建时也会同时创建布局文件。基于逻辑与视图的分离,最好每个活动都能对应一个布局。布局就是用来展示画面内容的。创建布局:layout下new -> layout resource file

    加载布局

    setContentView(R.layout.activity_main);

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/button_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="52dp"
            android:layout_marginLeft="52dp"
            android:layout_marginBottom="136dp"
            android:text="Button"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    :id 表示唯一标识符,之后可以在代码中操作这个view

    这里的+id在同一个xml文件里不能重名,在不同xml文件里可以重名

    +表示增加一个id,没有+号就是引用这个id

    view不加id和加id的区别

    https://blog.csdn.net/cyp331203/article/details/45313125

    注册活动

    所有活动必须在AndroidManifest.xml中注册

    ide会自动帮我们注册

    <activity android:name=".MainActivity"> // 活动名称
          <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
    </activity>
    

    使用原生toast

    1.上下文 2.文字 3.展示时间

    Toast.makeText(MainActivity.this,"click1",Toast.LENGTH_SHORT).show();

    使用menu

    在res目录下新建menu的资源文件夹->创建main的资源文件

    <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>
    

    <item>就是用来创建具体的某一个菜单项

    在activity中:

    重写方法

    	@Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // 第一个参数代表使用哪个资源文件
            // getMenuInflater表示获得一个menuInflater对象,再调用inflate方法
            getMenuInflater().inflate(R.menu.main,menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()) {
                case R.id.add_item:
                    Toast.makeText(this,"You clicked Add",Toast.LENGTH_SHORT).show();
                case R.id.remove_item:
                    Toast.makeText(this,"remove",Toast.LENGTH_SHORT).show();
            }
            return super.onOptionsItemSelected(item);
        }
    

    二、活动调用活动

    显式调用

    Intend是程序中各组件进行交互的一种重要方式,可以指明当前组件想要执行的动作,也可以在不同组件之间传递数据。可以用来启动活动,启动服务,以及发布广播等场景。

    // 第一个参数是上下文环境 打开SecondActivity这个活动
    Intent intent = new Intent(MainActivity.this,SecondActivity.class);
    startActivity(intent);
    

    start之后就进入了下一个活动

    隐式调用

    不明确想要启动哪一个活动,指定了一系列更为抽象的actioncategory等信息,然后交由系统去判断应该启动哪个活动。

    <activity android:name=".SecondActivity">
                <intent-filter>
                    <action android:name="activity.test.ACTION_START" /> 
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
    </activity>
    

    然后在代码中:

    Intent intent = new Intent("activity.test.ACTION_START");

    隐式调用可以一对多,即一个intend可以有多个活动供选择。一个动作用户可以选择不同的活动。

    这块还不清楚怎么用好

    三、活动之间传递数据

    传递简单数据

    系统提供了一系列putExtra()方法的重载,可以把想要传递的数据暂存在Intent中,启动另外一个活动时可以取出。

    String data = "Hello SecondActivity";
    intent.putExtra("extra_data",data);
    
    // 取出
    String data = intent.getStringExtra("extra_data");
    

    返回数据:

    startActivityForResult(intent,requestKey); // requestkey是请求码
    
    // 返回
    	@Override
        public void onBackPressed() {
            // Intent不仅可以启动活动,也是
           Intent intent = new Intent();
           intent.putExtra("data_return","hello mainActivity");
           setResult(RESULT_OK,intent);
           finish();
        }
    
    // 接收后
    	@Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            switch (requestCode) {
                case requestKey:
                    if (resultCode == RESULT_OK) {
                        String returnData = data.getStringExtra("data_return");
                        Toast.makeText(MainActivity.this, returnData, Toast.LENGTH_SHORT).show();
                    }
                    break;
                default:
                    break;
            }
        }
    

    通过bundle传递数据

    如果要传递多组数据,可以通过bundle的方式

    封装比较简单

    Bundle bundle = new Bundle();
    bundle.putInt("id",1);
    String data = "Hello SecondActivity";
    bundle.putString("extra_data",data);
    intent.putExtras(bundle);
    

    取出

    	@Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            Intent intent = getIntent();
            Bundle data = intent.getExtras();
            Toast.makeText(this,
                    String.format("id=%d,data=%s",data.getInt("id"),data.getString("extra_data")),
                    Toast.LENGTH_SHORT).show();
        }
    

    传递一个对象

    需要序列化

    @Data
    public class User implements Parcelable {
        private int id;
        private String name;
    
        public User(int id,String name) {
            this.id = id;
            this.name = name;
        }
    
        public User(Parcel source) {
            this.id = source.readInt();
            this.name = source.readString();
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        // 写进Parcel,一定要按照顺序
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(getId());
            dest.writeString(getName());
        }
    
        public static final Creator<User> CREATOR = new Creator<User>() {
            // 读取
            @Override
            public User createFromParcel(Parcel source) {
                return new User(source);
            }
    
            @Override
            public User[] newArray(int size) {
                return new User[size];
            }
        };
    }
    
    // 如果没有序列化下面这行代码就会报错
    intent.putExtra("user", new User(1,"name"));
    
    // 因为写入的是Parcelable类型,所以取出也要Parcelable
    User user = intent.getParcelableExtra("user");
    

    四、活动的生命周期

    深入理解生命周期的概念,可以写出更加连贯流畅的程序

    返回栈

    Android是使用Task管理活动,一个任务就是一组存放在栈里的活动的集合。

    启动一个新活动->活动入栈

    销毁一个活动 -> 栈顶弹出

    活动状态

    1.运行状态

    处于栈顶即处于运行状态,系统最不愿意回收运行状态的活动

    2.暂停状态

    当一个活动不处于栈顶位置,但任然可见,活动就进入暂停状态。如对话框。同样,这种状态系统也不愿意回收

    3.停止状态

    不处于栈顶,完全不可见,也就进入了停止状态。系统仍然会为这种活动保存相应的状态和活动变量,但是并不是完全可靠,当其他地方需要内存时,处于停止状态的活动有可能会被系统回收。

    4.销毁状态

    当一个活动从返回栈移除后就变成了销毁状态,系统会倾向于回收处于这种状态的活动,从而保证手机的内存充足。

    生命周期

    当activity启动时系统会先调用onCreate(),然后调用onStart(),最后调用onResume()方法,activity进入运行状态。

    当activity被别的activity 覆盖在其上时:系统会掉用onPause(),然后当覆盖在其上的activity会调用onCreate() -> onStart() -> onResume()后,第一个activity会调用onStop()方法使activity暂停。

    当覆盖在其上的第二个activity关闭返回此activity时,系统会先调用第二个activity的onPause()方法然后再调用第一个activity的onRestart() -> onStart() -> onResume()方法,进入运行状态,此时第二个activity才调用onStop() -> onDestroy()方法关闭。

    用户退出当前activity:系统先调用onPause(),然后调用onSotp(),最后调用onDestroy()方法,结束当前activity。


    • onRestart():表示activity正在重新启动,一般情况下是当前activity从不可见重新变成可见状态时,就会被调用,这种情况一般是用户行为导致的,如从其他页面返回当前页面时,或者用户按home键切换到桌面在重新打开app。

    • onStart()onStop():onStart()表示activity可见了,但是还没有获取焦点,无法进行交互。onStop()是和onStart()对应的当activity从可见转不可见是调用。

    • onResume()onPause():onResume()表示activity已经获取焦点了,可以进行交互了,onPause()是和onResume()方法对应的表示当前activity失去了焦点,此时可以做一些存储数据和停止动画等工作,但是不能太好时,不是会影响到新的activity的显示,因为只有onPause()执行完了,新的activity才会进入 onCreate() 等方法。

    • onDestroy():onDestroy()表示activity正在销毁,一般我们是在这进行资源的释放,以避免内存的泄漏。

    五、活动的启动模式

    https://blog.csdn.net/elisonx/article/details/80397519

    六、活动的最佳实践

    设置活动基类

    • 知晓当前处于哪个活动

    可能接手的是别人的代码,不清楚当前的页面是处于哪一个activity

    • 删除所有活动,退出程序

    如果有保存了所有activity的指针list,那就可以删除所有活动

    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 finishAll() {
            for (Activity activity : activities) {
                if (!activity.isFinishing()) {
                    activity.finish();
                }
            }
            activities.clear();
        }
    }
    
    public class BaseActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d("BaseActivity",getClass().getSimpleName());
            ActivityCollector.addActivity(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            ActivityCollector.removeActivity(this);
        }
    }
    

    启动活动的最佳写法

    如果启动活动需要一些关键的数据,之前的方法可能就是putExtra就行。但是这样可读性不好。

    如果A活动要启动B活动,可以在B活动定义一个方法,把需要的数据定义好,暴露这个方法给外界。A调用这个犯法start活动B,B活动开发时也对传入的数据一清二楚

    public class ThirdActivity extends AppCompatActivity {
    
        @SuppressLint("DefaultLocale")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_thrid);
            Intent intent = getIntent();
            Toast.makeText(this,
                    String.format("id=%d,name=%s",intent.getIntExtra("id",0),intent.getStringExtra("name")),
                    Toast.LENGTH_SHORT).show();
        }
    
        public static void actionStart(Context context,int id,String name) {
            Intent intent = new Intent(context, ThirdActivity.class);
            intent.putExtra("id",id); // 即需要id和name
            intent.putExtra("name",name);
            context.startActivity(intent);
        }
    }
    
    // 启动活动时很简单
    	private void handleClick() {
            Button button2 = (Button) findViewById(R.id.button_2);
            button2.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ThirdActivity.actionStart(SecondActivity.this,1,"name");
                }
            });
        }
    

    这样写避免了重复代码,如果说B会被很多个活动启动,把传入数据的相关代码下行到B是个很好的解决方法。

    不要忘记努力,不要辜负自己 欢迎指正 QQ:1468580561
  • 相关阅读:
    SpringBoot Actuator
    Mysql中实现row_number
    .添加索引和类型,同时设定edgengram分词和charsplit分词
    mysql临时禁用触发器
    centos6.7下安装mvn 、安装elasticsearch下ik分词
    ElasticSearch 自定义排序处理
    ElasticSearch返回不同的type的序列化
    Elasticsearch判断多列存在、bool条件组合查询示例
    C#多线程环境下调用 HttpWebRequest 并发连接限制
    centos6.7安装Redis
  • 原文地址:https://www.cnblogs.com/smallocean/p/14448435.html
Copyright © 2020-2023  润新知