• 安卓学习笔记


    控件

    控件1.TextView

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <TextView
            android:id="@+id/tv_one"
            android:text="@string/tv_one"
            android:textColor="@color/teal_700"
            android:textStyle="bold"
            android:textSize="25sp"
            android:background="@color/purple_200"
            android:gravity="center_horizontal"
            android:layout_width="200dp"
            android:="200dp"/>
    
    LinearLayout>
    
    id:组件id
    text:文本内容
    gravity:文本对齐方式
    layout_width:盒子宽度
    layout_height:盒子高度
    @string/tv_one定义在res/values/strings.xml中 可以设定字符串 通过name取值
    @color/teal_700同理
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    带阴影的TextView

    android:shadowColor:设置阴影颜色,需要和shadowRadius一起使用
    android:shadowRadius:设置阴影的模糊程度,设为0.1就变成字体颜色,建议3.0
    android:shadowDx:设置阴影在水平方向的偏移
    android:shadowDy:设置阴影在竖直方向的偏移
        <TextView
            android:id="@+id/tv_one"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:gravity="center_horizontal"
            android:shadowColor="@color/red"
            android:shadowRadius="3.0"
            android:text="@string/tv_one"
            android:shadowDx="10.0"
            android:shadowDy="10.0"
            android:textColor="@color/teal_700"
            android:textSize="25sp"
            android:textStyle="bold" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    跑马灯效果的TextView

    android:singleLine="true" //单行显示文本
    android:ellipsize="marquee" //跑马灯显示省略文本
    android:marqueeRepeatLimit="marquee_forever" //无限循环
    android:focusable="true" //可以获得焦点
    android:focusableInTouchMode="true"> //触屏获得焦点
    
    • 1
    • 2
    • 3
    • 4
    • 5

    获取焦点方法1.

    android:clickable="true"
    
    • 1

    添加点击获得焦点

    获取焦点方法2.

    public class MyTextView extends TextView {
        public MyTextView(Context context) {
            super(context);
        }
    
        public MyTextView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public boolean isFocused() {
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    重写TextView方法,默认一直获取焦点

    方法3.

    <requestFocus/>
    
    • 1

    加载就获取焦点

    控件2.Button

    <Button
        android:text="点击"
        android:textColor="@color/white"
        android:background="@drawable/btn_selector"
        android:backgroundTint="@color/btn_color_selector"
        android:layout_width="200dp"
        android:layout_height="100dp"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    @drawable可绘制图片

    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:drawable="@drawable/ic_baseline_account_balance_24" android:state_pressed="true"/>
    
        <item android:drawable="@drawable/ic_baseline_accessibility_24"/>
    
    selector>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在drawable创建btn_selector.xml设置按压一个图片,释放一个图片

    selector选择器,可以为颜色,图片等

    Button事件处理

    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG="leo";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn = findViewById(R.id.btn);
    
            //点击事件
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Log.e(TAG, "onClick: ");
                }
            });
    
            //长按事件
            btn.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    Log.e(TAG, "OnLongClick: ");
                    return false;
                }
            });
    
            //触摸事件
            btn.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    Log.e(TAG, "onTouch: "+motionEvent.getAction());
                    return false;
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    当返回值为false时,才会执行其他事件,若为true时,执行完此事件,不再接着执行

    也可以自定义事件

    <Button
        android:text="点击"
        android:textColor="@color/white"
        android:background="@drawable/btn_selector"
        android:backgroundTint="@color/btn_color_selector"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:onClick="myOnclick"
        android:id="@+id/btn"
        />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    public void myOnclick(View view) {
        Log.e(TAG, "OnLongClick: ");
    }
    
    • 1
    • 2
    • 3

    控件3.EditText

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <EditText
            android:id="@+id/et"
            android:hint="请输入用户名"
            android:inputType="phone"
            android:textColorHint="#95a1aa"
            android:layout_width="200dp"
            android:layout_height="100dp"/>
    
        <EditText
            android:hint="请输入用户名"
            android:inputType="textPassword"
            android:textColorHint="#95a1aa"
            android:drawableLeft="@drawable/ic_baseline_person_24"
            android:drawablePadding="5dp"
            android:background="@color/white"
            android:paddingLeft="5dp"
            android:layout_width="200dp"
            android:layout_height="100dp"/>
        <Button
            android:id="@+id/btn"
            android:text="获取用户名"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
        LinearLayout>
    hint:隐式提醒,输入内容时消失
    inputType:输入文本的内容
    drawableLeft:输入框的图片
    drawablePadding:图片与输入值间距
    paddingLeft:图标与左侧间距
     android:orientation="vertical":自适应布局
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    通过按钮获取输入框内容

    public class MainActivity extends AppCompatActivity {
    
        private EditText et;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button btn = findViewById(R.id.btn);
            et = findViewById(R.id.et);
    
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    String text = et.getText().toString();
                    Log.e("leo", "输入的内容"+text);
                }
            });
        }
    }
    /*
    设置按钮监听,然后点击获取输入框的文本值
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    控件4.ImageView

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/wuxing2"
        android:scaleType="fitCenter"
    
        />   
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/wuxing2"
        android:maxHeight="200dp"
        android:maxWidth="200dp"
        android:adjustViewBounds="true"
        />
      android:scaleType="fitCenter" :进行图片缩放
        android:maxHeight="200dp"
        android:maxWidth="200dp":设置最大宽高 前提开启adjustViewBounds
    android:adjustViewBounds="true":可以调整View的界限
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    控件5.ProgressBar

    
    <LinearLayout android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <ProgressBar
            android:id="@+id/pb"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="leonclick"
            android:text="显示或者隐藏进度条" />
    
        <ProgressBar
            android:id="@+id/pd2"
            style="?android:attr/progressBarStyleHorizontal"
            android:max="100"
            android:layout_width="300dp"
            android:layout_height="wrap_content"/>
        <Button
            android:onClick="loclick"
            android:text="模拟下载"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <ProgressBar
            android:indeterminate="true"
            style="?android:attr/progressBarStyleHorizontal"
            android:max="100"
            android:layout_width="300dp"
            android:layout_height="wrap_content"/>
    LinearLayout>
    
    
     style="?android:attr/progressBarStyleHorizontal":设置成水平进度条
      android:indeterminate="true":将进度条设置成不加载精度的进度条
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    点击事件

    public class MainActivity extends AppCompatActivity {
    
        private ProgressBar progressBar;
        private ProgressBar progressBar2;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            progressBar = findViewById(R.id.pb);
            progressBar2 = findViewById(R.id.pd2);
        }
    
        public void leonclick(View view) {
            if(progressBar.getVisibility()==View.GONE){
                progressBar.setVisibility(View.VISIBLE);
            }else{
                progressBar.setVisibility(View.GONE);
            }
        }
    
        public void loclick(View view) {
            int progress = progressBar2.getProgress();
            progress+=10;
            progressBar2.setProgress(progress);
        }
    }
    /*
    progressBar.getVisibility()==View.GONE:获取进度条的显示效果是否为隐藏
     progressBar2.getProgress()获取进度条的数值
    
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    控件6.Notificationn

    按钮

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发出通知"
            android:onClick="sendNotification"
            />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="取消通知"
            android:onClick="cacelNotification"
            />
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    public class MainActivity extends AppCompatActivity {
    
        private NotificationManager manager;
        private Notification notification;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    		//调用Context的getSystemService()方法获取,getSystemService()方法接收一个字符串参数用于确定获取系统那一个服务,这里是Context.NOTIFICATION_SERVICE。
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
                //该手机的操作系统版本号大于等于安卓6
                NotificationChannel channel = new NotificationChannel("leo", "测试通知", NotificationManager.IMPORTANCE_HIGH);//id需要和NotificationCompat的id一致  NotificationChannel的用户可见名称 和通知强度
                manager.createNotificationChannel(channel);//创建通知chan链
            }
    
            Intent intent = new Intent(this, NotificationActivity.class); //通信跳转到NotificationActivity
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
            //跳转到一个activity组件
            notification = new NotificationCompat.Builder(this,"leo") 
                    .setContentTitle("官方通知") //设置通知标题
                    .setContentText("开始学习安卓开发了") //设置通知内容
                    .setSmallIcon(R.drawable.ic_baseline_person_24) //设置通知小图标
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.wuxing))//设置通知大图标
                    .setColor(Color.parseColor("#ff0000"))//设置小图标颜色
                    .setContentIntent(pendingIntent)//设置通知点击跳转
                    .setAutoCancel(true)//设置通知点击消失
                    .build();//构建
        }
    
        public void sendNotification(View view) {
            manager.notify(1,notification);//点击发通知
        }
    
        public void cacelNotification(View view) {
            manager.cancel(1);//点击取消通知 id和发通知id一致
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    NotificationActivity

    package com.example.mynotification;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.util.Log;
    
    import androidx.annotation.Nullable;
    
    public class NotificationActivity extends Activity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    		//onCreate方法用来初始化Activity实例对象
            Log.e("leo", "onCreate: 进入notificationActivity" );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    需要add到related file xml中

    布局

    (一)线性布局LinearLayout

    线性布局在开发中使用最多,具有垂直方向与水平方向的布局方式,通过设置属性“android:orientation”控制方向,属性值垂直(vertical)和水平(horizontal),默认水平方向。
    android:gravity:内部控件对齐方式,常用属性值有center、center_vertical、center_horizontal、top、bottom、left、right等。
    这个属性在布局组件RelativeLayout、TableLayout中也有使用,FrameLayout、AbsoluteLayout则没有这个属性。
    center:居中显示,这里并不是表示显示在LinearLayout的中心,当LinearLayout线性方向为垂直方向时,center表示水平居中,但是并不能垂直居中,此时等同于center_horizontal的作用;同样当线性方向为水平方向时,center表示垂直居中,等同于center_vertical。
    top、bottom、left、right顾名思义为内部控件居顶、低、左、右布局。
    这里要与android:layout_gravity区分开,layout_gravity是用来设置自身相对于父元素的布局。
    android:layout_weight:权重,用来分配当前控件在剩余空间的大小。
    使用权重一般要把分配该权重方向的长度设置为零,比如在水平方向分配权重,就把width设置为零。

    二)相对布局RelativeLayout

    相对布局可以让子控件相对于兄弟控件或父控件进行布局,可以设置子控件相对于兄弟控件或父控件进行上下左右对齐。
    RelativeLayout能替换一些嵌套视图,当我们用LinearLayout来实现一个简单的布局但又使用了过多的嵌套时,就可以考虑使用RelativeLayout重新布局。
    相对布局就是一定要加Id才能管理。

    RelativeLayout中子控件常用属性:
    1、相对于父控件,例如:android:layout_alignParentTop=“true”
    android:layout_alignParentTop 控件的顶部与父控件的顶部对齐;
    android:layout_alignParentBottom 控件的底部与父控件的底部对齐;
    android:layout_alignParentLeft 控件的左部与父控件的左部对齐;
    android:layout_alignParentRight 控件的右部与父控件的右部对齐;

    2、相对给定Id控件,例如:android:layout_above=“@id/**”
    android:layout_above 控件的底部置于给定ID的控件之上;
    android:layout_below 控件的底部置于给定ID的控件之下;
    android:layout_toLeftOf 控件的右边缘与给定ID的控件左边缘对齐;
    android:layout_toRightOf 控件的左边缘与给定ID的控件右边缘对齐;
    android:layout_alignBaseline 控件的baseline与给定ID的baseline对齐;
    android:layout_alignTop 控件的顶部边缘与给定ID的顶部边缘对齐;
    android:layout_alignBottom 控件的底部边缘与给定ID的底部边缘对齐;
    android:layout_alignLeft 控件的左边缘与给定ID的左边缘对齐;
    android:layout_alignRight 控件的右边缘与给定ID的右边缘对齐;

    3、居中,例如:android:layout_centerInParent=“true”
    android:layout_centerHorizontal 水平居中;
    android:layout_centerVertical 垂直居中;
    android:layout_centerInParent 父控件的中央;

    (三)层布局FrameLayout

    帧布局或叫层布局,从屏幕左上角按照层次堆叠方式布局,后面的控件覆盖前面的控件。
    该布局在开发中设计地图经常用到,因为是按层次方式布局,我们需要实现层面显示的样式时就可以
    采用这种布局方式,比如我们要实现一个类似百度地图的布局,我们移动的标志是在一个图层的上面。
    在普通功能的软件设计中用得也不多。层布局主要应用就是地图方面。

    (四)绝对布局AbsoluteLayout

    绝对布局中将所有的子元素通过设置android:layout_x 和 android:layout_y属性,将子元素的坐标位置固定下来,即坐标(android:layout_x, android:layout_y) ,layout_x用来表示横坐标,layout_y用来表示纵坐标。屏幕左上角为坐标(0,0),横向往右为正方,纵向往下为正方。实际应用中,这种布局用的比较少,因为Android终端一般机型比较多,各自的屏幕大小。分辨率等可能都不一样,如果用绝对布局,可能导致在有的终端上显示不全等。所有基本不会使用,这里就不多介绍了。

    (五)表格布局TableLayout

    表格布局,适用于多行多列的布局格式,每个TableLayout是由多个TableRow组成,一个TableRow就表示TableLayout中的每一行,这一行可以由多个子元素组成。实际上TableLayout和TableRow都是LineLayout线性布局的子类。但是TableRow的参数android:orientation属性值固定为horizontal,且android:layout_width=MATCH_PARENT,android:layout_height=WRAP_CONTENT。所以TableRow实际是一个横向的线性布局,且所以子元素宽度和高度一致。
    注意:在TableLayout中,单元格可以为空,但是不能跨列,意思是只能不能有相邻的单元格为空。
    TableLayout常用属性:
    android:shrinkColumns:设置可收缩的列,内容过多就收缩显示到第二行
    android:stretchColumns:设置可伸展的列,将空白区域填充满整个列
    android:collapseColumns:设置要隐藏的列
    列的索引从0开始,shrinkColumns和stretchColumns可以同时设置。
    子控件常用属性:
    android:layout_column:第几列
    android:layout_span:占据列数

    (六)网格布局GridLayout

    作为android 4.0 后新增的一个布局,与前面介绍过的TableLayout(表格布局)其实有点大同小异;
    不过新增了一些东东
    ①跟LinearLayout(线性布局)一样,他可以设置容器中组件的对齐方式
    ②容器中的组件可以跨多行也可以跨多列(相比TableLayout直接放组件,占一行相比较)
    因为是android 4.0新增的,API Level 14,在这个版本以前的sdk都需要导入项目。这里不解释。

    常用属性:
    排列对齐:
    ①设置组件的排列方式: android:orientation=“” vertical(竖直,默认)或者horizontal(水平)
    ②设置组件的对齐方式: android:layout_gravity=“” center,left,right,buttom

    设置布局为几行几列:
    ①设置有多少行: android:rowCount=“4” //设置网格布局有4行
    ②设置有多少列: android:columnCount=“4” //设置网格布局有4列

    设置某个组件位于几行几列
    注:都是从0开始算的哦!
    ①组件在第几行: android:layout_row = “1” //设置组件位于第二行
    ②组件在第几列: android:layout_column = “2” //设置该组件位于第三列

    设置某个组件横跨几行几列(合并):
    横跨几行: android:layout_rowSpan = “2” //纵向横跨2行
    横跨几列: android:layout_columnSpan = “3” //横向横跨2列

    android:layout_gravity="fill"填充

    Menu

    选项菜单OptionMenu

    MainActivity

    package com.example.testmenu;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.view.ActionMode;
    import android.view.ContextMenu;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
        //创建OptionMenu
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            //加载菜单资源
            getMenuInflater().inflate(R.menu.option,menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
                case R.id.save:
                    Toast.makeText(this,"保存",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.exit:
                    Toast.makeText(this,"退出",Toast.LENGTH_SHORT).show();
                    break;
            }
            return super.onOptionsItemSelected(item);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    activity_main.xml

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
    
        <Button
            android:id="@+id/ctx_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="上下文菜单" />
    
        <Button
            android:id="@+id/popup_btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="弹出式菜单" />
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    上下文菜单ContextMenu

    两种实现方式,一种重写onCreateContextMenu,一种使用上下文操作模式

    package com.example.testmenu;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    import android.view.ActionMode;
    import android.view.ContextMenu;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    /*
            //注册contextmenu
            registerForContextMenu(findViewById(R.id.ctx_btn));
    
    */
        findViewById(R.id.ctx_btn).setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                startActionMode(cb);
                return false;
            }
        });
    
        }
    /*
        //创建
        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            getMenuInflater().inflate(R.menu.context,menu);
        }
    
        //菜单选的操做覆盖
        @Override
        public boolean onContextItemSelected(@NonNull MenuItem item) {
            switch(item.getItemId()){
                case R.id.delet:
                    Toast.makeText(this,"删除",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.opera1:
                    Toast.makeText(this,"操作1",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.opera2:
                    Toast.makeText(this,"操作2",Toast.LENGTH_SHORT).show();
                    break;
            }
            return super.onContextItemSelected(item);
        }
    */
    
        //为按钮设置上下文操作模式
        //实现ActionModeCallback接口
        ActionMode.Callback cb=new ActionMode.Callback() {
            //启动上下文操作模式时调用
            @Override
            public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                Log.e("TAG", "创建");
                getMenuInflater().inflate(R.menu.context,menu);
                return true;
            }
            //在创建方法后使用
            @Override
            public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                return true;
            }
    
            //菜单被点击
            @Override
            public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                Log.e("TAG", "点击");
                switch(menuItem.getItemId()){
                    case R.id.delet:
                        Toast.makeText(MainActivity.this,"删除",Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.opera1:
                        Toast.makeText(MainActivity.this,"操作1",Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.opera2:
                        Toast.makeText(MainActivity.this,"操作2",Toast.LENGTH_SHORT).show();
                        break;
                }
                return true;
            }
    
            //上下文操作结束时调用
            @Override
            public void onDestroyActionMode(ActionMode actionMode) {
                Log.e("TAG", "结束");
            }
        };
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    context.xml

    
    
    
        
        
            
                
                
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    通过java创建optionmenu菜单

      public boolean onCreateOptionsMenu(Menu menu) {
            //加载菜单资源
           // getMenuInflater().inflate(R.menu.option,menu);
            //组id 菜单项id 序号 菜单名称
            menu.add(1,1,1,"设置");
            SubMenu sub = menu.addSubMenu(1, 2, 2, "更多");
            sub.add(2,3,1,"添加");
            sub.add(2,4,1,"删除");
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            switch (item.getItemId()){
    /*            case R.id.save:
                    Toast.makeText(this,"保存",Toast.LENGTH_SHORT).show();
                    break;
                case R.id.exit:
                    Toast.makeText(this,"退出",Toast.LENGTH_SHORT).show();
                    break;*/
                case 1:
                    Toast.makeText(this,"设置",Toast.LENGTH_SHORT).show();
                    break;
                case 2:
                    Toast.makeText(this,"更多",Toast.LENGTH_SHORT).show();
                    break;
                case 3:
                    Toast.makeText(this,"添加",Toast.LENGTH_SHORT).show();
                    break;
                case 4:
                    Toast.makeText(this,"删除",Toast.LENGTH_SHORT).show();
                    break;
            }
            return super.onOptionsItemSelected(item);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    弹出菜单PopupMenu

        Button button=findViewById(R.id.popup_btn);
    findViewById(R.id.popup_btn).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //实例化PopupMenu对象
            PopupMenu menu = new PopupMenu(MainActivity.this,button);//出现在谁的下方
            //加载菜单资源,利用MenuInflater将Menu资源加载到PopupMenu.getMenu()返回的对象中
            menu.getMenuInflater().inflate(R.menu.popup,menu.getMenu());
            //设置点击监听
            menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem menuItem) {
                    switch (menuItem.getItemId()){
                        case R.id.copy:
                            Toast.makeText(MainActivity.this,"复制",Toast.LENGTH_SHORT).show();
                        break;
                        case R.id.paste:
                            Toast.makeText(MainActivity.this,"粘贴",Toast.LENGTH_SHORT).show();
                        break;
                    }
                    return false;
                }
            });
            //
            menu.show();
        }
    });
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    popup.xml

    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item
            android:id="@+id/copy"
            android:title="复制" />
        <item
            android:id="@+id/paste"
            android:title="粘贴" />
    menu>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    对话框

    AlterDialog提示对话框

    package com.example.dialogdemo;
    
    import androidx.appcompat.app.AlertDialog;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        //方法二
        public void  showNormalDialog(){
            AlertDialog builder=new AlertDialog.Builder(MainActivity.this).create();
            builder.setTitle("提示");
            builder.setMessage("您确定退出吗?");
            builder.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    
                }
            });
            builder.show();
        }
    
        //方法一
        public void myClick(View view) {
            switch (view.getId()){
                case R.id.normal_dialog_btn:
    
                    AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
                    builder.setTitle("提示");
                    builder.setMessage("您确定退出吗?");
                    //设置提示按钮,以及后续操作
                    builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            finish();
                        }
                    });
                    builder.setNegativeButton("取消",null);
                    builder.show();
                    /*
                    等价
                    AlertDialog alertDialog = builder.create();
                    alertDialog.show();
                     */
    
                    break;
                case R.id.diy_dialog_btn:
    
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    方法二设置按钮时不能传空操作

    Dialog

    设置按钮布局

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center_horizontal"
        android:background="@drawable/dialog"
        xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView
        android:textColor="#e61414"
        android:textStyle="bold|italic"
        android:layout_marginTop="290dp"
        android:textSize="34sp"
        android:text="@string/isexit"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
        <LinearLayout
            android:orientation="horizontal"
            android:layout_margin="25dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/yes_btn"
                android:background="@mipmap/yes"
                android:layout_marginRight="20dp"
                android:layout_width="70dp"
                android:layout_height="50dp"/>
              <Button
                  android:id="@+id/no_btn"
                  android:background="@mipmap/no"
                  android:layout_marginLeft="20dp"
                android:layout_width="70dp"
                android:layout_height="50dp"/>
        LinearLayout>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    package com.example.dialogdemo;
    
    import androidx.appcompat.app.AlertDialog;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.DialogInterface;
    import android.os.Bundle;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        //方法二
    /*
        public void  showNormalDialog(){
            AlertDialog builder=new AlertDialog.Builder(MainActivity.this).create();
            builder.setTitle("提示");
            builder.setMessage("您确定退出吗?");
            builder.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
    
                }
            });
            builder.show();
        }
    */
    
        //方法一
        public void myClick(View view) {
            switch (view.getId()){
                case R.id.normal_dialog_btn:
    
                    AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
                    builder.setTitle("提示");
                    builder.setMessage("您确定退出吗?");
                    //设置提示按钮,以及后续操作
                    builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            finish();
                        }
                    });
                    builder.setNegativeButton("取消",null);
                    builder.show();
                    /*
                    等价
                    AlertDialog alertDialog = builder.create();
                    alertDialog.show();
                     */
    
                    break;
                case R.id.diy_dialog_btn:
                    MyDialog myDialog = new MyDialog(this,R.style.mydialog);
                    myDialog.show();
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    activity.xml

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <Button
            android:id="@+id/normal_dialog_btn"
            android:text="@string/show_alter"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="myClick"
            />
        <Button
            android:id="@+id/diy_dialog_btn"
            android:text="@string/show_div_alter"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="myClick"
            />
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    定义一个类继承dialog

    public class MyDialog extends Dialog {
    
        public MyDialog(@NonNull Context context, int themeResId) {
            super(context, themeResId);
            setContentView(R.layout.dialog_layout);
    
            findViewById(R.id.yes_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    System.exit(0);
                }
            });
            findViewById(R.id.no_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dismiss();
                }
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    为按钮设置样式

    <style name="mydialog" parent="android:style/Theme.Dialog">
        "android:windowNoTitle">true
        "android:windowBackground">@color/white
    style>
    
    • 1
    • 2
    • 3
    • 4

    在mydialog中应用样式,为对话框添加监听器

    如果按钮图片没有加载出来则修改values/themes/themes.xml中

    <style name="Theme.Dialogdemo" parent="Theme.MaterialComponents.DayNight.DarkActionBar.Bridge">
    
    • 1

    四大组件

    1.Activity

    4种启动模式

    1.1SingTop

    只执行最上层的,如A,B,C,D,想执行B,则会添加B

    1.2singleTask

    顶部复用

    一个栈里一个activity只能有一个如A,B,C,D启动B,就会弹出C,D

    1.3standard默认模式

    先进先出,栈的模式

    1.4singleInstance

    独自占有一个栈,全局只有一个,如当前栈内是A,B,C,D需要启动E,则会新建栈E,如打电话

    生命周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UhcyNQIh-1660619680017)(C:\Users\TR\AppData\Roaming\Typora\typora-user-images\image-20220814175616933.png)]

    package com.example.activitylife;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.util.Log;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.i(TAG, "onCreate: ");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.i(TAG, "onStart: ");
        }
    
        //交互                                         
        @Override
        protected void onResume() {
            super.onResume();
            Log.i(TAG, "onResume: ");
        }
    
        //暂停
        @Override
        protected void onPause() {
            super.onPause();
            Log.i(TAG, "onPause: ");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.i(TAG, "onStop: ");
        }
    
        
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "onDestroy: ");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    线路一:正常打开到关闭一直往下

    线路二:打开另外的activity到onstop()后若返回键,则会到onrestart()再重新创建

    线路三:如进行浮窗类事件,则会触发onpause()返回则继续onresume

    线路四:终止

    补充:当actity销毁之前可以调用

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
    }
    
    • 1
    • 2
    • 3
    • 4

    把数据存储起来,在下次程序启动的时候,可以拿到数据

    当按返回键时触发

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }
    
    • 1
    • 2
    • 3
    • 4

    两个Activry之间的传递

    可以使用bundle 或则intent自带的常用类型

    package com.example.activitylife;
    
    import androidx.annotation.NonNull;
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.os.PersistableBundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.TextView;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MainActivity";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.i(TAG, "onCreate: ");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.i(TAG, "onStart: ");
        }
        //交互
        @Override
        protected void onResume() {
            super.onResume();
            Log.i(TAG, "onResume: ");
        }
    
        //暂停
        @Override
        protected void onPause() {
            super.onPause();
            Log.i(TAG, "onPause: ");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.i(TAG, "onStop: ");
        }
    
        @Override
        public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
            super.onSaveInstanceState(outState, outPersistentState);
        }
    
        @Override
        public void onBackPressed() {
            super.onBackPressed();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.i(TAG, "onDestroy: ");
        }
    
        public void myclick(View view) {
            Intent intent = new Intent(MainActivity.this,SecondActivity.class);
            Bundle bundle = new Bundle();
            bundle.putString("name","bundle消息");
            bundle.putChar("开头",'A');
            intent.putExtra("name",bundle);
            startActivity(intent);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    secondactivity

    package com.example.activitylife;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.widget.Button;
    import android.widget.TextView;
    
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    
    public class SecondActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.second_activity);
            if(getIntent()!=null){
                Bundle bundle = getIntent().getBundleExtra("name");
                if(bundle!=null){
                    String name = bundle.getString("name");
                    Button button = findViewById(R.id.sec);
                    button.setText(name);
                }
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    activity.xml

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <Button
            android:id="@+id/btn_onn"
            android:onClick="myclick"
            android:text="@string/secondactivity"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    second.xml

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:id="@+id/sec"
            android:textSize="35sp"
            android:text="@string/seconnd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    序列化传输

    传输序列化后的对象

    public class User implements Serializable{
        private String title;
    
        public class BaseInfo implements Serializable{}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    序列化的类的方法也需要序列化

    public void myclick(View view) {
        intent.putExtra("",new User());
    }
    
    • 1
    • 2
    • 3

    实现关闭SecondActivity或返回时把值传给MainActivity

    startActivityForResult(intent,999);
    
    • 1

    使用Result传入标识符

    SecondActivity添加监听

    public void seclick(View view) {
        setResult(RESULT_OK);
        finish();
    }
    
    • 1
    • 2
    • 3
    • 4

    MainActivity添加接收判断

    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.i(TAG, "onActivityResult:启动了 ");
        if(requestCode == 999 && requestCode == RESULT_OK){
            Log.i(TAG, "onActivityResult: 成功了!");
            setTitle("前一个页面返回啦!!");
        }else {
            setTitle("返回失败了!!");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    也可直接关闭的时候传入Inent 返回的时候在public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 的data接收

    2.Service服务

    生命周期

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OOK5pLfm-1660619680018)(C:\Users\dofun008\AppData\Roaming\Typora\typora-user-images\image-20220815091236288.png)]

    启动服务

    MainActivity

    package com.example.servicedemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void operate(View view) {
            switch (view.getId()){
                case R.id.start_:
                    //启动服务
                    Intent intent = new Intent(this,MyService.class);
                    startService(intent);
                    break;
                case R.id.stop_:
                    //停止服务
                    Intent intent1 = new Intent(this,MyService.class);//无论开启几个意图还是操作同一个对象
                    stopService(intent1);
                    break;
    
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    activity_main.xml

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        xmlns:android="http://schemas.android.com/apk/res/android">
        <Button
            android:id="@+id/start_"
            android:text="启动服务"
            android:onClick="operate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/stop_"
            android:text="停止服务"
            android:onClick="operate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/bind_"
            android:text="绑定服务"
            android:onClick="operate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <Button
            android:id="@+id/unbind_"
            android:text="解除服务"
            android:onClick="operate"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    Myservice

    package com.example.servicedemo;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.util.Log;
    
    public class MyService extends Service {
        private static final String TAG = "Ms";
        public MyService() {
        }
    
        //创建
        @Override
        public void onCreate() {
            Log.e(TAG, "onCreate: ");
            super.onCreate();
        }
    
        //启动
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e(TAG, "onStartCommand: " );
           return super.onStartCommand(intent, flags, startId);
        }
    
        //绑定
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            Log.e(TAG, "onBind: " );
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        //解绑
        @Override
        public boolean onUnbind(Intent intent) {
            Log.e(TAG, "onUnbind: " );
            return super.onUnbind(intent);
        }
    
        //摧毁
        @Override
        public void onDestroy() {
            Log.e(TAG, "onDestroy: " );
            super.onDestroy();
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    启动服务,通过onCreate,onStartCommand方法,停止服务经过onDestroy,再次启动则会重新创建

    服务对象只会存在一个,若服务已经创建,后续启动的都是同一个服务,除非先销毁它

    服务的生命周期和Activity无关,除非手动关闭

    绑定服务
    package com.example.servicedemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        private ServiceConnection conn=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void operate(View view) {
            switch (view.getId()){
                case R.id.start_:
                    //启动服务
                    Intent intent = new Intent(this,MyService.class);
                    startService(intent);
                    break;
                case R.id.stop_:
                    //停止服务
                    Intent intent1 = new Intent(this,MyService.class);//无论开启几个意图还是操作同一个对象
                    stopService(intent1);
                    break;
                case R.id.bind_:
                    //绑定服务
                    Intent intent2 = new Intent(this,MyService.class);
                    bindService(intent2, conn,BIND_AUTO_CREATE);
                    break;
                case R.id.unbind_:
                    //解绑服务
    
                    unbindService(conn);
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    服务不存在,执行绑定,先创建服务,再绑定服务,执行解绑,先解绑,再销毁。

    服务存在,bindService只能被onBind调用,unbindService只能被onUnbind调用

    注意:绑定服务不会启动服务,不会在后台启动,只绑定不启动,退出后台后,服务会销毁

    进度监控

    IBinder:在android中用于远程操作对象的一个基本接口

    //绑定
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e(TAG, "onBind: " );
        return new Binder();
    }
    //对于onBind方法而言,要求返回IBinder对象
    //实际上,我们会自己定义一个内部类,继承Binder类
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //用于绑定客户端和服务
    private ServiceConnection conn=new ServiceConnection() {
        //当客户端正常连接着服务时,执行服务的绑定会被调用
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.e("TAG", "onServiceConnected: " );
        }
    
        //当客户端和服务的连接丢失了
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e("TAG", "onServiceDisconnected: " );
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    服务器解绑后无法再次绑定,然而每次重新绑定会执行

    onServiceConnected()方法

    所以需要IBind来传值

    package com.example.servicedemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
    
        //用于绑定客户端和服务
        private ServiceConnection conn=new ServiceConnection() {
            //当客户端正常连接着服务时,执行服务的绑定会被调用
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Log.e("TAG", "onServiceConnected: " );
                MyService.MyBinder mb= (MyService.MyBinder) iBinder;
                int process = mb.getProcess();
                Log.e("TAG", "当前进度是: "+process );
            }
    
            //当客户端和服务的连接丢失了
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                Log.e("TAG", "onServiceDisconnected: " );
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void operate(View view) {
            switch (view.getId()){
                case R.id.start_:
                    //启动服务
                    Intent intent = new Intent(this,MyService.class);
                    startService(intent);
                    break;
                case R.id.stop_:
                    //停止服务
                    Intent intent1 = new Intent(this,MyService.class);//无论开启几个意图还是操作同一个对象
                    stopService(intent1);
                    break;
                case R.id.bind_:
                    //绑定服务
                    Intent intent2 = new Intent(this,MyService.class);
                    bindService(intent2, conn,BIND_AUTO_CREATE);
                    break;
                case R.id.unbind_:
                    //解绑服务
    
                    unbindService(conn);
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    开启线程,传递进度

    package com.example.servicedemo;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.util.Log;
    
    import java.util.concurrent.TimeUnit;
    
    public class MyService extends Service {
        private int i;
        private static final String TAG = "Ms";
        public MyService() {
        }
    
        //创建
        @Override
        public void onCreate() {
            Log.e(TAG, "onCreate: ");
            super.onCreate();
            //开启一个线程。开启耗时任务,(从1到100)
            new Thread(()->{
                for (i = 1; i <=100; i++) {
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        //启动
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.e(TAG, "onStartCommand: " );
           return super.onStartCommand(intent, flags, startId);
        }
    
        //绑定
        @Override
        public IBinder onBind(Intent intent) {
            // TODO: Return the communication channel to the service.
            Log.e(TAG, "onBind: " );
            return new MyBinder();
        }
        //对于onBind方法而言,要求返回IBinder对象
        //实际上,我们会自己定义一个内部类,继承Binder类
    
        class MyBinder extends Binder{
            //定义自己需要的方法(实现进度监控)
            public int getProcess(){
                return i;
            }
    
        }
        //解绑
        @Override
        public boolean onUnbind(Intent intent) {
            Log.e(TAG, "onUnbind: " );
            return super.onUnbind(intent);
        }
    
        //摧毁
        @Override
        public void onDestroy() {
            Log.e(TAG, "onDestroy: " );
            super.onDestroy();
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    onBind的类的返回值IBinder刚好可以作为ServiceConnection.onServiceConnected的返回值,但是由于IBinder类需要实现很多方法,不方便,于是使用他的实现类Binder类来做返回值,可以自定义自己需要的业务

    2.2AIDL通信

    不同进程之间,数据共享,数据通信

    创建新的项目aidldemo1

    package com.example.aidldemo1;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    import android.view.View;
    
    public class MainActivity extends AppCompatActivity {
        ServiceConnection conn=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                Log.e("Ms", "onServiceConnected: " );
            }
    
            @Override
            public void onServiceDisconnected(ComponentName componentName) {
                Log.e("Ms", "onServiceDisconnected: " );
            }
        };
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public void operate(View view) {
            switch (view.getId()){
                case R.id.start_:
                    //远程启动服务
                   //Intent intent = new Intent("com.liu.myservice");
                   Intent intent = new Intent();
                   intent.setAction("com.liu.myservice");
                    intent.setPackage("com.example.servicedemo");
                    startService(intent);
                    break;
                case R.id.stop_:
                    //远程停止服务
                   // Intent intent1 = new Intent("com.liu.myservice");
                    Intent intent1 = new Intent();
                    intent1.setAction("com.liu.myservice");
                    intent1.setPackage("com.example.servicedemo");
                    stopService(intent1);
                    break;
                case R.id.bind_:
                    //远程绑定服务
                    //Intent intent2 = new Intent("com.liu.myservice");
                     Intent intent2 = new Intent();
                    intent2.setAction("com.liu.myservice");
                    intent2.setPackage("com.example.servicedemo");
                    bindService(intent2, conn,BIND_AUTO_CREATE);
                    break;
                case R.id.unbind_:
                    //远程解绑服务
                    unbindService(conn);
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    给原来项目的service起别名

    <activity
        android:name=".MainActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
    
            <category android:name="android.intent.category.LAUNCHER" />
        intent-filter>
    activity>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意,这个Intent传值一定要显式声明

    远程通信

    创建aidl资源

    // IMyAidlInterface.aidl
    package com.example.serviceaidldemo;
    
    // Declare any non-default types here with import statements
    
    interface IMyAidlInterface {
        /**
         * Demonstrates some basic types that you can use as parameters
         * and return values in AIDL.
         */
        void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                double aDouble, String aString);
    
    
            void showProgress();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    rebuild项目

    改写传值方法,因为IBinder只能同一个项目传值

    MyService改写onbind

    //绑定
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e(TAG, "onBind: " );
        return new IMyAidlInterface.Stub() {
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
    
            }
    
            @Override
            public void showProgress() throws RemoteException {
                Log.e(TAG, "aidl显示的进度为"+i);
            }
        };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    MainActivity改写

    //用于绑定客户端和服务
    private ServiceConnection conn=new ServiceConnection() {
        //当客户端正常连接着服务时,执行服务的绑定会被调用
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.e("Ms", "onServiceConnected: " );
            IMyAidlInterface imai = IMyAidlInterface.Stub.asInterface(iBinder);
            try {
                imai.showProgress();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在aidldemo中创建aidl 创建下一级目录需要和主程序的包名一直

    ,复制aidl文件,并rebuilder

    改写传输代码

    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    
        IMyAidlInterface imit = IMyAidlInterface.Stub.asInterface(iBinder);
        try {
            imit.showProgress();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    AIDL本质是生成Java类,自己写实现,如同搭建了桥梁

    3.ContentProvider

    创建两个项目dataproviderdemo和dataresoverdemo

    在dataproviderdemo创建other ContentPovider方法

    package com.example.dataproviderdemo;
    
    import android.content.ContentProvider;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.net.Uri;
    
    public class MyContentProvider extends ContentProvider {
        public MyContentProvider() {
        }
    
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            // Implement this to handle requests to delete one or more rows.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public String getType(Uri uri) {
            // TODO: Implement this to handle requests for the MIME type of the data
            // at the given URI.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO: Implement this to handle requests to insert a new row.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public boolean onCreate() {
            // TODO: Implement this to initialize your content provider on startup.
            return false;
        }
    
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                            String[] selectionArgs, String sortOrder) {
            // TODO: Implement this to handle query requests from clients.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    
        @Override
        public int update(Uri uri, ContentValues values, String selection,
                          String[] selectionArgs) {
            // TODO: Implement this to handle requests to update one or more rows.
            throw new UnsupportedOperationException("Not yet implemented");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    在dataresoverdemo使用dataproviderdemo暴露的方法

    在MyContentProvider中onCreate方法中创建数据库

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        SQLiteOpenHelper sqLiteOpenHelper=new SQLiteOpenHelper(getContext(),"stu.db",null,1) {
            @Override
            public void onCreate(SQLiteDatabase sqLiteDatabase) {
    
                String sql="create table info_tb (_id integer primary key autoincrement,"
                        +"name varchar(20),"
                        +"age integer,"
                        +"gender varchar(2))";
                sqLiteDatabase.execSQL(sql);
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    
            }
        };
        db = sqLiteOpenHelper.getReadableDatabase();
    
        //返回true
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    添加方法

    case R.id.add_btn:
        ContentValues values = new ContentValues();
        values.put("name",name);
        values.put("age",age);
        values.put("gender",genderstr);
        //返回值是MyContentProvider中insert传入的值
        Uri uri = resolver.insert(Uri.parse("content://com.liu.myprovider"), values);//参数1:URI对象
        //解析返回的uri的id
        long id = ContentUris.parseId(uri);
        Toast.makeText(MainActivity.this, "添加成功,新学生的学号是"+id, Toast.LENGTH_SHORT).show();
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    contentprovider

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        Log.e("TAG", "调用了DataProviderDemo中的insert方法");
        long id = db.insert("info_tb", null, values);
        //将id追加到uri后面
        return  ContentUris.withAppendedId(uri,id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里resover解析uri然后传入数据,然后接收到contentprovider的ContentUris的方法携带的参数id作为添加成功的依据

    查询操作

    重写provider的query方法

    contentprovider

    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        Cursor c = db.query("info_tb", projection, selection, selectionArgs, null, null, sortOrder);
        return c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    resover

    case R.id.select_btn:
        //查询、
    
        Cursor cursor = null;
        if(!idedt.equals("")){
            cursor = resolver.query(uri, null, "_id=?", new String[]{idedt}, null);;
        }else {
            cursor = resolver.query(uri, null, null, null, null);;
        }
    
        if(cursor!=null){
            SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,cursor,
                    new String[]{"_id","name","age","gender"},
                    new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},
                    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//页面更新
            stulist.setAdapter(adapter);
        }else {
            Toast.makeText(MainActivity.this, "查无此人", Toast.LENGTH_SHORT).show();
        }
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    删除

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        int result = db.delete("info_tb", selection, selectionArgs);
        return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    case R.id.delet_btn:
        //删除、
        int i = resolver.delete(uri, "_id=?", new String[]{idedt});
        if(i>0){
            Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
        }
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    修改操作

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        int tb = db.update("info_tb", values, selection, selectionArgs);
        return tb;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
        case R.id.update_btn:
            //修改、
            ContentValues values1 = new ContentValues();
            values1.put("name",name);
            values1.put("age",age);
            values1.put("gender",genderstr);
            int update = resolver.update(uri, values1, "_id=?", new String[]{idedt});
            if (update>0){
                Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(MainActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
            }
    
            break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里,已经很明显了,contentprovider为resover提供接口,resover请求contentprovider的方法,操作contentprovider的数据,然后收到其返回值

    SQLite数据库

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。

    下载SQLite Expert

    SQL语句

    activity_main.xml

    
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="10dp"
        xmlns:android="http://schemas.android.com/apk/res/android">
    
        <EditText
            android:id="@+id/name_edt"
            android:hint="姓名:"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <EditText
            android:id="@+id/age_edt"
            android:numeric="integer"
            android:hint="年龄:"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <RadioGroup
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
           <TextView
               android:text="性别:"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"/>
            <RadioButton
                android:id="@+id/man"
                android:text=""
                android:layout_marginLeft="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
            <RadioButton
                android:id="@+id/woman"
                android:text=""
                android:layout_marginLeft="5dp"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        RadioGroup>
        <EditText
            android:id="@+id/id_edt"
            android:hint="编号"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/add_btn"
                android:text="添加"
                android:onClick="opera"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
            <Button
                android:onClick="opera"
                android:id="@+id/select_btn"
                android:text="查询"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
            <Button
                android:onClick="opera"
                android:id="@+id/delet_btn"
                android:text="删除"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
            <Button
                android:onClick="opera"
                android:id="@+id/update_btn"
                android:text="修改"
                android:layout_marginLeft="5dp"
                android:layout_weight="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        LinearLayout>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    编写按钮处理事件

    package com.example.sqlitetest;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.CursorAdapter;
    import android.widget.EditText;
    import android.widget.ListView;
    import android.widget.RadioGroup;
    import android.widget.SimpleCursorAdapter;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
        private EditText nameEdt,ageEdt,idEdt;
        private RadioGroup genderGp;
        private String genderstr="男";
        private SQLiteDatabase db;
        private String sql;
        private ListView stulist;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            stulist=findViewById(R.id.stu_list);
            nameEdt=findViewById(R.id.name_edt);
            ageEdt=findViewById(R.id.age_edt);
            idEdt=findViewById(R.id.id_edt);
            genderGp=findViewById(R.id.gender_gp);
            genderGp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {
                    if(i==R.id.man){
                        //男
                        genderstr="男";
                    }else {
                        genderstr="女";
                    }
                }
            });
    
            //添加、
            //操作对象, 数据库名称
            //如果只有一个数据库名称,那么这个数据库位置会在私有目录中 data/data
            //如果带SD卡路径,那么数据库位置则会在指定的路径下
            //String path = Environment.getExternalStorageDirectory() + "/stu.db";
            SQLiteOpenHelper helper=new SQLiteOpenHelper(this,"test3.db",null,1) {
                @Override
                public void onCreate(SQLiteDatabase sqLiteDatabase) {
                    //创建
                    Toast.makeText(MainActivity.this, "数据库创建", Toast.LENGTH_SHORT).show();
                    String sql="create table test_tb1(_id integer primary key autoincrement,"
                            +"name varchar(20),"+
                            "age integer,"+"gender varchar(6) )"
                            ;
                    sqLiteDatabase.execSQL(sql);
                }
    
                @Override
                public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
                    //升级
                    Toast.makeText(MainActivity.this, "数据库升级", Toast.LENGTH_SHORT).show();
    
                }
            };
            //获取数据库对象
            //数据库存在则打开数据库,数据库不存在则打开数据库
            //数据库存在,但版本号升高了,则调用数据库升级方法
            db = helper.getReadableDatabase();
            //查询 db.rawQuery();
            //增删改创  db.execSQL();
        }
    
    
        public void opera(View view) {
            switch (view.getId()){
                case R.id.add_btn:
    
                    String name=nameEdt.getText().toString();
                    String age=ageEdt.getText().toString();
    
                   // String sql="insert into test_tb1 (name,age,gender) values('"+name+"',"+age+",'"+genderstr+"') ";
                   sql="insert into test_tb1 (name,age,gender) values(?,?,?) ";
                    db.execSQL(sql,new String[]{name,age,genderstr});
                    Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.delet_btn:
                    //删除、
                    sql="delete from test_tb1 where _id=?";
                    db.execSQL(sql,new String[]{idEdt.getText().toString()});
                    Toast.makeText(MainActivity.this, "删除成功", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.select_btn:
                    //查询、
                    if(!idEdt.getText().toString().equals("")){
                        sql+="where _id="+idEdt.getText().toString();
                    }
                    sql="select * from test_tb1";
                    //查询结果
                    Cursor cursor = db.rawQuery(sql, null);
    
                    //
                    SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,cursor,
                            new String[]{"_id","name","age","gender"},
                            new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},
                            CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//页面更新
                    stulist.setAdapter(adapter);
                    break;
                case R.id.update_btn:
                    //修改、
                    sql="update test_tb1 set name=?,age=?,gender=? where _id=?";
                    db.execSQL(sql,new String[]{nameEdt.getText().toString(),ageEdt.getText().toString(),genderstr,idEdt.getText().toString()});
                    Toast.makeText(MainActivity.this, "修改成功", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121

    使用了Viewlist要设置适配器

    item.xml

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/name_item"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/age_item"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/id_item"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
        <TextView
            android:id="@+id/gender_item"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意:

    如果用的虚拟机,不要把数据库路径写在SD卡中,会闪退

    需要借助SQLiteOpenHelper类然后创建数据库或者打开,

    使用helper.getReadableDatabase()得到SQLiteDatabase对象,

    然后可以对数据库进行增删改查等操作

    使用API对数据进行操作

    添加insert()

    switch (view.getId()){
        case R.id.add_btn:
    
            ContentValues values = new ContentValues();
            values.put("name",name);
            values.put("age",age);
            values.put("gender",genderstr);
            long id = db.insert("test_tb1", null, values);//表名,可以为空的列,参数
            Toast.makeText(MainActivity2.this, "添加成功,新学员学号是:"+id, Toast.LENGTH_SHORT).show();
            break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第二个参数依据第三个参数而定是否为null

    查询query()

    case R.id.select_btn:
        //查询、
        //参数1:表名 参数2:列(查询全部为null或者{"*"})
        // 参数3:条件(列1=? 多值为列1=? and 列2=?)参数4:条件的参数 参数5:分组
        //参数6:分组条件限定 参数7:排序
        Cursor cursor = db.query("test_tb1",null,null,null,null,null,null);
    
        SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,cursor,
                new String[]{"_id","name","age","gender"},
                new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//页面更新
        stulist.setAdapter(adapter);
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    删除delete()

    case R.id.select_btn:
        //查询、
        //参数1:表名 参数2:列(查询全部为null或者{"*"})
        // 参数3:条件(列1=? 多值为列1=? and 列2=?)参数4:条件的参数 参数5:分组
        //参数6:分组条件限定 参数7:排序
        Cursor cursor = db.query("test_tb1",null,null,null,null,null,null);
    
        SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,cursor,
                new String[]{"_id","name","age","gender"},
                new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//页面更新
        stulist.setAdapter(adapter);
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    修改

        case R.id.update_btn:
            //修改、
            ContentValues values1 = new ContentValues();
            values1.put("name",name);
            values1.put("age",age);
            values1.put("gender",genderstr);
            int i = db.update("test_tb1", values1, "_id=?", new String[]{idedt});
            if(i>0){
                Toast.makeText(MainActivity2.this, "修改成功", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(MainActivity2.this, "修改失败啦", Toast.LENGTH_SHORT).show();
    
            }
    
            break;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    条件查询

    case R.id.select_btn:
        //查询、
        //参数1:表名 参数2:列(查询全部为null或者{"*"})
        // 参数3:条件(列1=? 多值为列1=? and 列2=?)参数4:条件的参数 参数5:分组
        //参数6:分组条件限定 参数7:排序
        Cursor cursor = null;
        if(!idedt.equals("")){
            cursor = db.query("test_tb1",null,"_id=?",new String[]{idedt},null,null,null);
        }else {
            cursor = db.query("test_tb1",null,null,null,null,null,null);
        }
    
        if(cursor!=null){
            SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,cursor,
                    new String[]{"_id","name","age","gender"},
                    new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},
                    CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//页面更新
            stulist.setAdapter(adapter);
         }else {
            Toast.makeText(MainActivity2.this, "查无此人", Toast.LENGTH_SHORT).show();
        }
        break;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    InnoDB和MyISAM区别
    git及dbc的学习
    SpringBoot 自动配置@EnableAutoConfiguration
    Vue ref 和 v-for 结合(ref 源码解析)
    Spring Cloud Stream 消息驱动基础入门与实践总结
    11.3 读图举例
    【机器学习基础】无监督学习(2)——降维之LLE和TSNE
    内核网络协议栈传输层协议框架
    自定义控件——视图的构建过程——视图的绘制方法
    go + uniapp 通过 微信 code 获取 appid 等信息 无废话
  • 原文地址:https://blog.csdn.net/liuwushuang233/article/details/126362250