[移动端]Android开发笔记(上)

1,270 阅读21分钟

Android笔记(2021.9.12-2021.11.26)

0.应用清单预览

1.每个应用项目必须在项目源设置的根目录中加入 AndroidManifest.xml 文件(且必须使用此名称)。

1.软件包名称和应用 ID

清单文件的根元素需包含应用软件包名称(通常与项目目录结构,即 Java 命名空间相匹配)的属性。

例如,以下代码段显示包含软件包名称 "com.example.myapp"manifest 根元素:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    android:versionCode="1"
    android:versionName="1.0" >
    ...
</manifest>

2.应用组件

对于在应用中创建的每个应用组件,您必须在清单文件中声明相应的 XML 元素:

  • <activity> 用于 Activity 的每个子类。
  • <service> 用于 Service 的每个子类。
  • <receiver> 用于 BroadcastReceiver 的每个子类。
  • <provider> 用于 ContentProvider 的每个子类。

3.权限

如要访问敏感用户数据(如联系人和短信)或某些系统功能(如相机和互联网访问),则 Android 应用必须请求相关权限。 每个权限均由唯一标签标识。 例如,如果应用需要发送短信,则必须在清单中添加以下代码行:

<manifest ... >
    <uses-permission android:name="android.permission.SEND_SMS"/>
    ...
</manifest>

4.设备兼容性

清单文件也可用于声明应用所需的硬件或软件功能类型,以及应用兼容的设备类型。 Google Play 商店不允许在未提供应用所需功能或系统版本的设备上安装应用。

某些清单标签可定义与应用兼容的设备。 以下是一些最常见的此类标签。

5.文件约定

此部分描述普遍适用于清单文件中所有元素和属性的约定和规则。

  • 元素

    只有 <manifest><application> 元素是必需的, 二者必须且只能出现一次。 大多数其他元素可以不出现或多次出现。 但是,必须提供某些元素才能使清单文件发挥作用。必须通过属性(而非以元素内的字符数据形式)设置所有值。同一级别的元素通常不分先后顺序。 例如,<activity><provider><service> 元素可按任何顺序放置。 这条规则有两个主要的例外情况:<activity-alias> 元素必须跟在别名所指的 <activity> 之后。<application> 元素必须是 <manifest> 元素内的最后一个元素。

  • 属性

    严格来说,所有属性都是可选的。 但是,必须指定某些属性才可让元素实现其目的。 对于真正可选的属性, [参考文档会指定默认值。除了根 <manifest> 元素的某些属性外,所有属性名称均以 android: 前缀开头。 例如,android:alwaysRetainTaskState。 由于该前缀是通用的,因此在按名称引用属性时,参考文档通常会将其忽略。

  • 多个值

    如果可以指定多个值,则几乎总是在重复元素,而非列出单个元素内的多个值。 例如,Intent 过滤器可以列出多个操作

    <intent-filter ... >
        <action android:name="android.intent.action.EDIT" />
        <action android:name="android.intent.action.INSERT" />
        <action android:name="android.intent.action.DELETE" />
        ...
    </intent-filter>
    
  • 资源值

    某些属性的值可以显示给用户,例如,Activity 的标题或应用图标。 这些属性的值可能因用户的语言或其他设备配置而异(例如根据设备的像素密度提供不同的图标大小),因此您应根据资源或主题设置值,而非将其硬编码到清单文件中。 随后,您可根据为不同设备配置提供的备用资源更改实际值。资源将通过以下格式表示为值:"@[package:]type/name"如果资源由您的应用提供,则您可以忽略软件包名称(其亦适用于资源由库依赖项提供的情况,因为 库资源会合并到您的资源中)。 当您想要使用 Android 框架中的资源时,唯一的其他有效包名称是 android。type 是资源类型(例如 stringdrawable),name 是标识特定资源的名称。 下面是示例:<activity android:icon="@drawable/smallPic" ... >有关如何在项目中添加资源的更多信息,请阅读提供资源。如要应用主题中定义的值,第一个字符必须是 ?,而非

    @"?[package:]type/name"

  • 字符串值

    如果属性值为字符串,则您必须使用双反斜杠 (\) 来转义字符,例如:使用 \n 表示换行符或使用 \uxxxx 表示 Unicode 字符。

    6.清单元素参考

下表提供 AndroidManifest.xml 文件中所有有效元素的参考文档链接。

<action>向 Intent 过滤器添加操作。
<activity>声明 Activity 组件。
<activity-alias>声明 Activity 的别名。
<application>应用的声明。
<category>向 Intent 过滤器添加类别名称。
<compatible-screens>指定与应用兼容的每个屏幕配置。
<data>向 Intent 过滤器添加数据规范。
<grant-uri-permission>指定父级内容提供程序有权访问的应用数据的子集。
<instrumentation>声明支持您监控应用与系统进行交互的 Instrumentation 类。
<intent-filter>指定 Activity、服务或广播接收器可以响应的 Intent 类型。
<manifest>AndroidManifest.xml 文件的根元素。
<meta-data>可以提供给父级组件的其他任意数据项的名称-值对。
<path-permission>定义内容提供程序中特定数据子集的路径和所需权限。
<permission>声明安全权限,可用于限制对此应用或其他应用的特定组件或功能的访问。
<permission-group>为相关权限的逻辑分组声明名称。
<permission-tree>声明权限树的基本名称。
<provider>声明内容提供程序组件。
<receiver>声明广播接收器组件。
<service>声明服务组件。
<supports-gl-texture>声明应用支持的一种 GL 纹理压缩格式。
<supports-screens>声明应用支持的屏幕尺寸,并为大于此尺寸的屏幕启用屏幕兼容模式。
<uses-configuration>指明应用要求的特定输入功能。
<uses-feature>声明应用使用的单个硬件或软件功能。
<uses-library>指定应用必须链接到的共享库。
<uses-permission>指定为使应用正常运行,用户必须授予的系统权限。
<uses-permission-sdk-23>指明应用需要特定权限,但仅当应用在运行 Android 6.0(API 级别 23)或更高版本的设备上安装时才需要。
<uses-sdk>您可以通过整数形式的 API 级别,表示应用与一个或多个版本的 Android 平台的兼容性。

7.清单文件示例

以下 XML 文件为 AndroidManifest.xml 的一个简单示例,该示例为应用声明两个 Activity。

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:versionCode="1"
    android:versionName="1.0"
    package="com.example.myapp">
​
    <!-- Beware that these values are overridden by the build.gradle file -->
    <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" />
​
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
​
        <!-- This name is resolved to com.example.myapp.MainActivity
             based upon the package attribute -->
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
​
        <activity
            android:name=".DisplayMessageActivity"
            android:parentActivityName=".MainActivity" />
    </application>
</manifest>

一.UI

1.控件

1.TextView

1.基础属性详解

image.png

image.png

2.阴影

image.png

3.跑马灯效果

image.png

<TextView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/text"
       android:text="texttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttexttextv"
       android:textSize="100sp"
       android:textStyle="bold"
       android:gravity="center"
       android:shadowColor="@color/teal_200"
       android:shadowDx="10.0"
       android:shadowDy="10.0"
       android:shadowRadius="3.0"
       android:singleLine="true"
       android:ellipsize="marquee"
       android:marqueeRepeatLimit="marquee_forever"
       android:focusable="true"
       android:focusableInTouchMode="true">
       <requestFocus></requestFocus>
   </TextView>

2.Button

1. 基础

image.png

<Button
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:background="@drawable/btn_selector"
        android:backgroundTint="@color/color_selector"
        android:text="划水"
        android:textSize="50sp"/>

color_selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!--    颜色选择器-->
    <item android:color="#ffffff00" android:state_pressed="true"/>
    <item android:color="#0ffff000"/>
</selector>

btn_selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">

<!--    图片选择器-->
    <item android:drawable="@drawable/ic_baseline_account_box_24" android:state_pressed="true"/>
    <item android:drawable="@drawable/ic_baseline_access_time_24"/>
</selector>

2.事件处理

1.点击

2.长按

3.触摸

Button btn = findViewById(R.id.button);
        
        // 单击
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: ");
            }
        });
​
        // 长按
        btn.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Log.d(TAG, "onLongClick: ");
                return false;
            }
        });
​
        // 触摸
        btn.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Log.d(TAG, "onTouch: ");
                return false;
            }
        });

3.EditText

1.基础(继承TextView,属性也继承)

image.png

///xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入用户名"
        android:inputType="phone"
        android:textColorHint="@color/teal_200"/>

    <EditText
        android:id="@+id/password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入密码"
        android:inputType="textPassword"
        android:textColorHint="@color/teal_700"/>

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="点击获取"
        android:gravity="center_vertical"/>

</LinearLayout>

///Java代码
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);

        Button btn = findViewById(R.id.button);
        EditText account = findViewById(R.id.account);
        EditText password = findViewById(R.id.password);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "onClick: " + account.getText().toString());
                Log.d(TAG, "onClick: " +password.getText().toString());
            }
        });
    }
}

4.ImageView

1.基础

image.png

2.缩放类型

image.png

 <ImageView
        android:id="@+id/image1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_launcher"/>

5.ProgressBar

1.基础

image.png

/// xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <ProgressBar
        android:id="@+id/pb"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="显示/隐藏"/>

    <ProgressBar
        android:id="@+id/pb2"
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="load"/>

    <ProgressBar
        style="?android:attr/progressBarStyleHorizontal"
        android:max="100"
        android:indeterminate="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

// Java文件
ProgressBar progressBar = findViewById(R.id.pb);
Button button = findViewById(R.id.btn1);

ProgressBar progressBar2 = findViewById(R.id.pb2);
Button button2 = findViewById(R.id.btn2);

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if (progressBar.getVisibility() == View.GONE){
            progressBar.setVisibility(view.VISIBLE);
        }else {
            progressBar.setVisibility(View.GONE);
        }
    }
});

button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        int progress = progressBar2.getProgress();
        Log.d("log", "progress: " + progress);
        progress += 10;
        progressBar2.setProgress(progress);
    }
});

6.Notification

1.基础

image.png

image.png

/// xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"/>
    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="sendNotification"
        android:text="发送通知"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="cancel"
        android:text="取消通知"/>

</LinearLayout>

//Java代码
public class MainActivity extends AppCompatActivity {

    private NotificationManager manger;
    private Notification notification;

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        manger = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            NotificationChannel channel = new NotificationChannel("heng", "测试通知",
                    NotificationManager.IMPORTANCE_HIGH);

            manger.createNotificationChannel(channel);
        }

        Intent intent = new Intent(this, MyActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

        notification = new NotificationCompat.
                Builder(this,"heng")
                .setContentTitle("恒宝,饿吗?")
                .setContentText("午饭没吃,现在晚饭吃吗?")
                .setSmallIcon(R.drawable.ic_launcher_background)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),
                        R.drawable.ic_baseline_format_bold_24))
                .setColor(Color.parseColor("#00ff00"))
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .build();
    }

    public void sendNotification(View view) {
        manger.notify(1,notification);
    }

    public void cancel(View view) {
        manger.cancel(1);

    }
}

-------------------------------------------------------------------------

/**
 * @author : HengBao
 * @date : 2021/10/13 16:24
 */

public class MyActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d("MyActivity", "onCreate: ");

    }
}

7.ToolBar

1.基础

image.png

//xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tb"
        android:background="#ff00ff"
        app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
        app:title="标题"
        app:titleTextColor="@color/teal_700"
        app:titleMarginStart="90dp"
        android:subtitle="子标题"
        android:logo="@drawable/ic_launcher_background"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"/>


    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tb2"
        android:layout_marginTop="20dp"
        android:background="#ffff00"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"/>

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tb3"
        android:layout_marginTop="20dp"
        android:background="#ffff00"
        android:layout_width="match_parent"
        app:navigationIcon="@drawable/ic_baseline_arrow_back_24"
        android:layout_height="?android:attr/actionBarSize">
        <TextView
            android:text="标题"
            android:layout_gravity="center"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </androidx.appcompat.widget.Toolbar>

</LinearLayout>

//Java文件
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);

        Toolbar toolbar = findViewById(R.id.tb);

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "toolbar 被点击了  onClick: ");

            }
        });

        Toolbar toolbar1 = findViewById(R.id.tb2);
        toolbar1.setTitle("划水");
        toolbar1.setNavigationIcon(R.drawable.ic_baseline_arrow_back_24);

        toolbar1.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "toolbar1 被点击了  ");

            }
        });

        Toolbar toolbar2 = findViewById(R.id.tb3);

        toolbar2.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d(TAG, "toolbar 被点击了  onClick: ");
                Toast.makeText(MainActivity.this,"你点击了back",Toast.LENGTH_SHORT).show();
            }
        });
    }
}

8.AlertDialog

1.基础

image.png

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn1"
        android:text="显示"
        android:onClick="showClock"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
-------------------------------------------------------
mine_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:background="#ffdd00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:src="@mipmap/ic_launcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="好久不见"/>
</LinearLayout>

//Java文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn1"
        android:text="显示"
        android:onClick="showClock"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
-------------------------------------------------------
mine_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:background="#ffdd00"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:src="@mipmap/ic_launcher"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="好久不见"/>
</LinearLayout>

9.PopupWindow

1.基础

image.png

main_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:text="弹出PopupWindow"
        android:onClick="showClick"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>
-------------------------------------------------------
mine_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:background="@mipmap/ic_launcher"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="上海"/>

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="北京"/>
</LinearLayout>

//Java文件

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void showClick(View view) {
        View popupView = getLayoutInflater().inflate(R.layout.layout_popupwindow, null);

        Button btn1 = popupView.findViewById(R.id.btn1);
        Button btn2 = popupView.findViewById(R.id.btn2);


        PopupWindow popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT,
                                                  ViewGroup.LayoutParams.WRAP_CONTENT,true);
        popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_launcher_foreground));

        popupWindow.showAsDropDown(view);

        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"你是喜欢上海吗?",Toast.LENGTH_SHORT).show();
                popupWindow.dismiss();
            }
        });

        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this,"你是喜欢北京吗?",Toast.LENGTH_SHORT).show();
                popupWindow.dismiss();
            }
        });
    }
}

2.布局

1.LinearLayout(线性布局)

1.基础

image.png

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@drawable/img"
    android:dividerPadding="100dp"
    android:showDividers="middle"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#ff00ff"/>

    <!--分割线-->
    <View
        android:layout_width="match_parent"
        android:layout_height="10dp"
        android:background="@color/teal_200"/>
    
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#1100ff"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#ff5511"/>
</LinearLayout>

2.RelativeLayout(相对布局)

1.基础

image.png

2.通用属性

image.png

3.FrameLayout(流布局 || 帧布局)

1.基础

image.png

这个是层叠的

image.png

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:foreground="@drawable/ic_launcher_foreground"
        android:foregroundGravity="right"
        android:background="#0000ff"/>

    <TextView
        android:layout_width="200dp"
        android:layout_height="180dp"
        android:background="#00ff00"/>

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:background="@color/black"/>

</FrameLayout>

4.TableLayout(表格布局)

1.基础

image.png

5.GridLayout(网格布局)

1.基础

image.png

image.png

6.ConstraintLayout(约束布局)

1.基础

在左侧的designer中直接拖动

image.png

3.两个View

1.ListView

1.基础

layout_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
--------------------------------------------------------------------
layout_listview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text1"
        android:gravity="left"
        android:textSize="20sp"
        android:background="@color/teal_700"
        android:layout_width="match_parent"
        android:layout_height="30dp"/>

</LinearLayout>

//Java文件
main:
public class MainActivity extends AppCompatActivity {

    private List<MyBean> data = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        for (int i = 0; i < 30; i++) {
            MyBean myBean = new MyBean();
            myBean.setName("划水 :" + i);
            data.add(myBean);
        }

        //找到主界面的listview
        ListView listView = findViewById(R.id.listView);
        //设置适配器
        listView.setAdapter(new MyAdapter(data, this));
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this,"点击了: " + i,Toast.LENGTH_SHORT).show();
                Log.d("data", "onItemClick: " + i);
            }
        });
    }
}
---------------------------------------------------------------
    myBean:

public class MyBean {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
-------------------------------------------------------------
    myAdapter:

public class MyAdapter extends BaseAdapter {

    private List<MyBean> data;
    private Context context;

    public MyAdapter() {
    }

    public MyAdapter(List<MyBean> data, Context context) {
        this.data = data;
        this.context = context;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder viewHolder;

        if (convertView == null) {

            viewHolder = new ViewHolder();

            //绑定layout_listview布局
            convertView = LayoutInflater.from(context).inflate(R.layout.layout_listview, parent, false);

            //获取textview
            viewHolder.textView = convertView.findViewById(R.id.text1);

            convertView.setTag(viewHolder);
        }else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        //设置值
        viewHolder.textView.setText(data.get(position).getName());

        //        Log.d("adapter", "getView: " + position);

        return convertView;
    }

    private final class ViewHolder{
        TextView textView;
    }
}

2.RecyclerView

1.基础

image.png

main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycleView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
------------------------------------------------------
layout_recycleview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text1"
        android:gravity="left"
        android:textSize="20sp"
        android:background="@color/teal_700"
        android:layout_width="match_parent"
        android:layout_height="30dp"/>

</LinearLayout>

//Java文件


    public class MainActivity extends AppCompatActivity {

        private List<MyBean> data = new ArrayList<>();

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            for (int i = 0; i < 200; i++) {
                MyBean myBean = new MyBean();
                myBean.setName("划水 :" + i);
                data.add(myBean);
            }

            RecyclerView recyclerView = findViewById(R.id.recycleView);

            //设置布局
            //线性布局
            //        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
            //        recyclerView.setLayoutManager(linearLayoutManager);
            //网格布局
            //        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
            //        recyclerView.setLayoutManager(gridLayoutManager);
            //流布局
            StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, LinearLayout.VERTICAL);
            recyclerView.setLayoutManager(staggeredGridLayoutManager);
            MyAdapter myAdapter = new MyAdapter(data, this);
            recyclerView.setAdapter(myAdapter);

            myAdapter.setOnRecycleItemClickListener(new MyAdapter.OnRecycleItemClickListener() {
                @Override
                public void onRecycleItemClick(int position) {
                    Toast.makeText(MainActivity.this,"点击了: " + position,Toast.LENGTH_SHORT).show();
                    Log.d("data", "onItemClick: " + position);
                }
            });

        }
    }
-----------------------------------------------------
    myadapter:

/**
 * @author : HengZhang
 * @date : 2021/10/15 13:35
 */

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private List<MyBean> data;
    private Context context;

    //构造方法
    public MyAdapter(List<MyBean> data, Context context) {
        this.data = data;
        this.context = context;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        //找到布局
        View view = View.inflate(context, R.layout.layout_recycleview, null);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

        //赋值
        holder.textView.setText(data.get(position).getName());

    }

    @Override
    public int getItemCount() {
        return data == null ? 0 : data.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView textView;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);

            //找到textview
            textView = itemView.findViewById(R.id.text1);

            //配置点击事件
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if (onRecycleItemClickListener != null){
                        onRecycleItemClickListener.onRecycleItemClick(getAdapterPosition());
                    }
                }
            });
        }
    }

    //设置点击事件
    private OnRecycleItemClickListener onRecycleItemClickListener;

    public void setOnRecycleItemClickListener(OnRecycleItemClickListener listener){
        onRecycleItemClickListener = listener;
    }

    public interface OnRecycleItemClickListener{
        void onRecycleItemClick(int position);
    }
}
----------------------------------------------------------
    mybean:
package com.example.recyclerview;

/**
 * @author : HengZhang
 * @date : 2021/10/15 12:40
 */

public class MyBean {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

4.动画

1.分类

image.png

2.帧动画

1.基础

image.png

/drawable/frame.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/image1" android:duration="200"/>
    <item android:drawable="@drawable/image2" android:duration="200"/>
    <item android:drawable="@drawable/image3" android:duration="200"/>
    <item android:drawable="@drawable/image4" android:duration="200"/>
    <item android:drawable="@drawable/image5" android:duration="200"/>
</animation-list>
---------------------------------------------------------------
main_layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/relativeLayout"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="@drawable/frame"
    tools:context=".MainActivity">
</RelativeLayout>

//Java文件
public class MainActivity extends AppCompatActivity {

    private boolean flag = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RelativeLayout relativeLayout = findViewById(R.id.relativeLayout);
        AnimationDrawable anim = (AnimationDrawable) relativeLayout.getBackground();
        relativeLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (flag) {
                    anim.start();
                    flag = false;
                } else {
                    anim.stop();
                    flag = true;
                }
            }
        });
    }
}

3.补间动画

1.基础

image.png

layout_main:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:adjustViewBounds="true"
        android:maxHeight="400dp"
        android:maxWidth="400dp"
        android:src="@drawable/image3"/>

</RelativeLayout>
--------------------------------------------------------------
/anim/alpha.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--透明度设置 ,duration:时间,周期-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <alpha
        android:duration="5000"
        android:fromAlpha="0"
        android:toAlpha="1" />

</set>
----------------------------------------------------------------
/anim/rotate.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--旋转-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="0%"
        android:pivotY="0%"
        android:duration="2000"
        />

</set>
------------------------------------------------------------
/anim/scale.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--缩放-->
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <scale
        android:duration="1000"
        android:fromXScale="0.5"
        android:fromYScale="0.5"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1"
        android:toYScale="1" />
</set>
--------------------------------------------------------------
/anim/translate.xml:
<?xml version="1.0" encoding="utf-8"?>
<!--平移-->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="400"
        android:toYDelta="400" />
</set>

//Java文件
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = findViewById(R.id.imageView);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //通过加载xml文件创建Animation对象

                //1.透明度
                Animation animation1 = AnimationUtils.loadAnimation(MainActivity.this,
                                                                    R.anim.alpha);

                //2.旋转
                Animation animation2 = AnimationUtils.loadAnimation(MainActivity.this,
                                                                    R.anim.rotate);

                //3.缩放
                Animation animation3 = AnimationUtils.loadAnimation(MainActivity.this,
                                                                    R.anim.scale);

                //4.平移
                Animation animation4 = AnimationUtils.loadAnimation(MainActivity.this,
                                                                    R.anim.trantslate);
                imageView.startAnimation(animation1);

            }
        });
    }
}

4.属性动画

1.基础

image.png

image.png

image.png

监听器的adapter可以选择需要的方法调用

5.单位和尺寸

image.png

image.png

image.png

6.ViewPager

1.基础

image.png

main_layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
------------------------------------------------------------
layout1.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/teal_700"
        android:gravity="bottom|center"
        android:text="我是layout1"
        android:textSize="50sp"/>

</LinearLayout>
-------------------------------------------------------
layout2.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/teal_200"
        android:gravity="center"
        android:text="我是layout2"
        android:textSize="50sp" />

</LinearLayout>
------------------------------------------------------------
layout3.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#f60566"
        android:gravity="right|center"
        android:text="我是layout3"
        android:textSize="50sp"/>

</LinearLayout>

//Java文件

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LayoutInflater inflater = getLayoutInflater().from(this);
        View view1 = inflater.inflate(R.layout.layout1,null);
        View view2 = inflater.inflate(R.layout.layout2,null);
        View view3 = inflater.inflate(R.layout.layout3,null);

        ArrayList<View> myList = new ArrayList<>();
        myList.add(view1);
        myList.add(view2);
        myList.add(view3);

        ViewPager viewPager = findViewById(R.id.vp);
        MyAdapter myAdapter = new MyAdapter(myList);
        viewPager.setAdapter(myAdapter);
    }
}
----------------------------------------------------
MyAdapter.java:

/**
 * @author : HengZhang
 * @date : 2021/10/16 13:19
 */

public class MyAdapter extends PagerAdapter {
    private List<View> myListView;

    public MyAdapter(List<View> myListView) {
        this.myListView = myListView;
    }

    @Override
    public int getCount() {
        return myListView.size();
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        container.addView(myListView.get(position),0);

        return myListView.get(position);
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView(myListView.get(position));

    }
}

二.Fragment

1.什么是fragment

image.png

image.png

2.fragment使用

1.简单使用

main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/fragment1"
        android:name="com.example.fragment.BlankFragment1"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:background="@color/black"/>

    <fragment
        android:id="@+id/fragment2"
        android:name="com.example.fragment.BlankFragment2"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>
----------------------------------------------------------
fragment_blank1.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".BlankFragment1">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="@string/hello_blank_fragment" />

    <Button
        android:id="@+id/btn"
        android:text="how are you?"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

//Java文件
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
-----------------------------------------------------------------
fragment:
public class BlankFragment1 extends Fragment {
    private View inflate;
    private TextView textView;
    private Button button;


    public BlankFragment1() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        inflate = inflater.inflate(R.layout.fragment_blank1,container,false);
        textView = inflate.findViewById(R.id.textView);
        button = inflate.findViewById(R.id.btn);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                textView.setText("yes,you too!");
            }
        });
        return inflate;
    }
}

2.动态添加fragment

image.png

main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="change" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="replace" />

    <FrameLayout
        android:id="@+id/fragmentLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/teal_200"/>

</LinearLayout>

//Java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button1 = findViewById(R.id.btn1);
        Button button2 = findViewById(R.id.btn2);
        button1.setOnClickListener(this);
        button2.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn1:
                replaceFragment(new BlankFragment1());
                break;
            case R.id.btn2:
                replaceFragment(new ItemFragment1());
                break;
            default:
                break;
        }
    }

    //动态replace fragment
    public void replaceFragment(Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();

        transaction.replace(R.id.fragmentLayout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
    }
}

3.Activity与Fragment通信

image.png

main:
@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btn1:

            //Activity与Fragment通信
            Bundle bundle = new Bundle();
            bundle.putString("mgs","hello,long time no see!");
            BlankFragment1 fragment1 = new BlankFragment1();
            fragment1.setArguments(bundle);

            replaceFragment(fragment1);
            break;
        case R.id.btn2:
            replaceFragment(new ItemFragment1());
            break;
        default:
            break;

    }

}
-----------------------------
    BlankFragment1    
    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //Activity与Fragment通信
    Bundle bundle = this.getArguments();
    String mgs = bundle.getString("mgs");
    Log.d("TAG", "onCreate: " + mgs);


    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

4.接口

image.png

package com.example.fragmentmanager;

/**
 * @author : HengZhang
 * @date : 2021/10/17 12:22
 * 接口实现activity和fragment通信
 */

public interface IFragmentCallback {
    //从activity中收到消息
    String getMsgFromActivity(String msg);

    //向activity发送消息
    void sendMsgToActivity(String msg);
}
-------------------------------------------------------------
main:
 //接口通信
  fragment1.setIFragmentCallback(new IFragmentCallback() {
      @Override
      public String getMsgFromActivity(String msg) {
          return "hi,i`m from activity";
      }

      @Override
      public void sendMsgToActivity(String msg) {
          Toast.makeText(MainActivity.this,
                  msg,Toast.LENGTH_SHORT).show();

      }
  });
-------------------------------------------------------------
Blackfragment:
 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        if (rootView == null){
            rootView = inflater.inflate(R.layout.fragment_blank1, container, false);
        }

        //发消息到activity
        Button button1 = rootView.findViewById(R.id.fragmentBtn1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                iFragmentCallback.sendMsgToActivity("hello,i`m from fragment!");
            }
        });

        //收消息到fragment
        Button button2 = rootView.findViewById(R.id.fragmentBtn2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String msg = iFragmentCallback.getMsgFromActivity("null");
                Toast.makeText(BlankFragment1.this.getContext(),msg,Toast.LENGTH_SHORT).show();

            }
        });
        return rootView;

5.Frgment声明周期

image.png

image.png

image.png

3.Frament与ViewPager的联合使用

image.png

三.四大组件

activity、service,content provider,broadcast receiver

1.activity

1.概述

Activity 类是 Android 应用的关键组件,而 Activity 的启动和组合方式则是该平台应用模型的基本组成部分。

2.管理 Activity 生命周期

image.png

一个 Activity 在其生命周期中会经历多种状态。您可以使用一系列回调来处理状态之间的转换。下面几节将介绍这些回调。

onCreate()

您必须实现此回调,它会在系统创建您的 Activity 时触发。您的实现应该初始化 Activity 的基本组件:例如,您的应用应该在此处创建视图并将数据绑定到列表。最重要的是,您必须在此处调用 setContentView() 来定义 Activity 界面的布局。该逻辑在 Activity 的整个生命周期中只应发生一次。

onCreate() 完成后,下一个回调将是 onStart()

onStart()

onCreate() 退出后,Activity 将进入“已启动”状态,并对用户可见。此回调包含 Activity 进入前台与用户进行互动之前的最后准备工作。

onResume()

系统会在 Activity 开始与用户互动之前调用此回调。此时,该 Activity 位于 Activity 堆栈的顶部,并会捕获所有用户输入。应用的大部分核心功能都是在 onResume() 方法中实现的。

onResume() 回调后面总是跟着 onPause() 回调。

onPause()

当 Activity 失去焦点并进入“已暂停”状态时,系统就会调用 onPause()。例如,当用户点按“返回”或“最近使用的应用”按钮时,就会出现此状态。当系统为您的 Activity 调用 onPause() 时,从技术上来说,这意味着您的 Activity 仍然部分可见,但大多数情况下,这表明用户正在离开该 Activity,该 Activity 很快将进入“已停止”或“已恢复”状态。

如果用户希望界面继续更新,则处于“已暂停”状态的 Activity 也可以继续更新界面。例如,显示导航地图屏幕或播放媒体播放器的 Activity 就属于此类 Activity。即使此类 Activity 失去了焦点,用户仍希望其界面继续更新。

应使用 onPause() 来保存应用或用户数据、进行网络呼叫或执行数据库事务。

onPause() 执行完毕后,下一个回调为 onStop()onResume(),具体取决于 Activity 进入“已暂停”状态后发生的情况。

onStop()

当 Activity 对用户不再可见时,系统会调用 onStop()。出现这种情况的原因可能是 Activity 被销毁,新的 Activity 启动,或者现有的 Activity 正在进入“已恢复”状态并覆盖了已停止的 Activity。在所有这些情况下,停止的 Activity 都将完全不再可见。

系统调用的下一个回调将是 onRestart()(如果 Activity 重新与用户互动)或者 onDestroy()(如果 Activity 彻底终止)。

onRestart()

当处于“已停止”状态的 Activity 即将重启时,系统就会调用此回调。onRestart() 会从 Activity 停止时的状态恢复 Activity。

此回调后面总是跟着 onStart()

onDestroy()

系统会在销毁 Activity 之前调用此回调。

此回调是 Activity 接收的最后一个回调。通常,实现 onDestroy() 是为了确保在销毁 Activity 或包含该 Activity 的进程时释放该 Activity 的所有资源。

3.activity之间的切换

main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="change"
        android:text="切换"/>
</LinearLayout>

//Java文件
/**
 * activity的生命周期
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void change(View view) {
        Intent intent = new Intent(this,Activity2.class);
        Toast.makeText(this,"change to Activity2!",Toast.LENGTH_SHORT).show();
        startActivity(intent);
    }
}

2.service

1.概览

Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行.

2.三种不同的服务类型

  • 前台

    前台服务执行一些用户能注意到的操作。例如,音频应用会使用前台服务来播放音频曲目。前台服务必须显示[通知]。即使用户停止与应用的交互,前台服务仍会继续运行。

  • 后台

    后台服务执行用户不会直接注意到的操作。例如,如果应用使用某个服务来压缩其存储空间,则此服务通常是后台服务。

  • 绑定

    当应用组件通过调用 bindService() 绑定到服务时,服务即处于绑定状态。绑定服务会提供客户端-服务器接口,以便组件与服务进行交互、发送请求、接收结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

##!!注意:

服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行(除非另行指定)。如果服务将执行任何 CPU 密集型工作或阻止性操作(例如 MP3 播放或联网),则应通过在服务内创建新线程来完成这项工作。通过使用单独的线程,您可以降低发生“应用无响应”(ANR) 错误的风险,而应用的主线程仍可继续专注于运行用户与 Activity 之间的交互。

3.基础知识

如要创建服务,必须创建 Service 的子类(或使用它的一个现有子类)。在实现中,必须重写一些回调方法,从而处理服务生命周期的某些关键方面,并提供一种机制将组件绑定到服务(如适用)。

方法:

onStartCommand(): 当另一个组件(如 Activity)请求启动服务时,系统会通过调用 startService() 来调用此方法。执行此方法时,服务即会启动并可在后台无限期运行。如果您实现此方法,则在服务工作完成后,您需负责通过调用 stopSelf()stopService() 来停止服务。(如果您只想提供绑定,则无需实现此方法。)

onBind() : 当另一个组件想要与服务绑定(例如执行 RPC)时,系统会通过调用 bindService() 来调用此方法。在此方法的实现中,必须通过返回 IBinder 提供一个接口,以供客户端用来与服务进行通信。务必实现此方法;但是,如果并不希望允许绑定,则应返回 null。

onCreate() : 首次创建服务时,系统会(在调用 onStartCommand()onBind() 之前)调用此方法来执行一次性设置程序。如果服务已在运行,则不会调用此方法。

onDestroy() :

当不再使用服务且准备将其销毁时,系统会调用此方法。服务应通过实现此方法来清理任何资源,如线程、注册的侦听器、接收器等。这是服务接收的最后一个调用。


注意:

1.如果组件通过调用 startService() 启动服务(这会引起对 onStartCommand() 的调用),则服务会一直运行,直到其使用 stopSelf() 自行停止运行,或由其他组件通过调用 stopService() 将其停止为止。

2.如果组件通过调用 bindService() 来创建服务,且未调用 onStartCommand(),则服务只会在该组件与其绑定时运行。当该服务与其所有组件取消绑定后,系统便会将其销毁。

4.服务的生命周期

服务的生命周期比 Activity 的生命周期要简单得多。但是,密切关注如何创建和销毁服务反而更加重要,因为服务可以在用户未意识到的情况下运行于后台。

服务生命周期(从创建到销毁)可遵循以下任一路径:

  • 启动服务

    该服务在其他组件调用 startService() 时创建,然后无限期运行,且必须通过调用 stopSelf() 来自行停止运行。此外,其他组件也可通过调用 stopService() 来停止此服务。服务停止后,系统会将其销毁。

  • 绑定服务

    该服务在其他组件(客户端)调用 bindService() 时创建。然后,客户端通过 IBinder 接口与服务进行通信。客户端可通过调用 unbindService() 关闭连接。多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务。(服务不必自行停止运行。)

image.png

这两条路径并非完全独立。您可以绑定到已使用 startService() 启动的服务。例如,您可以使用 Intent(标识要播放的音乐)来调用 startService(),从而启动后台音乐服务。随后,当用户需稍加控制播放器或获取有关当前所播放歌曲的信息时,Activity 可通过调用 bindService() 绑定到服务。此类情况下,在所有客户端取消绑定之前,stopService()stopSelf() 实际不会停止服务。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开启服务"/>

    <Button
        android:id="@+id/bind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="绑定"/>

    <Button
        android:id="@+id/unBind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="解绑"/>

    <Button
        android:id="@+id/stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="关闭服务"/>

</LinearLayout>

//Java文件
main:

/**
 * service
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button start = findViewById(R.id.start);
        start.setOnClickListener(this);
        Button stop = findViewById(R.id.stop);
        stop.setOnClickListener(this);
        Button bind = findViewById(R.id.bind);
        bind.setOnClickListener(this);
        Button unBind = findViewById(R.id.unBind);
        unBind.setOnClickListener(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(connection);
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.start:
                serviceStart();
                Toast.makeText(this, "开始service!", Toast.LENGTH_SHORT).show();
                break;

            case R.id.stop:
                serviceStop();
                Toast.makeText(this, "停止service!", Toast.LENGTH_SHORT).show();
                break;

            case R.id.bind:
                serviceBind();
                Toast.makeText(this, "绑定service!", Toast.LENGTH_SHORT).show();
                break;

            case R.id.unBind:
                serviceUnBind();
                Toast.makeText(this, "解绑service!", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
    }

    //MainActivity 与 service 的媒介
    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    private void serviceUnBind() {
        unbindService(connection);
    }

    private void serviceBind() {
        bindService(new Intent(this, MyService.class),
                connection, Context.BIND_AUTO_CREATE);

    }

    private void serviceStop() {
        stopService(new Intent(this, MyService.class));
    }

    private void serviceStart() {
        startService(new Intent(this, MyService.class));
    }
}
---------------------------------------------------------------
service:


/**
 * @author : HengZhang
 * @date : 2021/10/17 18:36
 */

public class MyService extends Service {

    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind: ");
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.d(TAG, "onUnbind: ");
        return super.onUnbind(intent);
    }
}

3.Broatcast Receiver

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/staticAction"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="静态广播" />

    <Button
        android:id="@+id/dynamicAction"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="动态广播" />

</LinearLayout>

//Java文件
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.d(TAG, "onCreate: ");
        Button staticAction = findViewById(R.id.staticAction);
        staticAction.setOnClickListener(this);
        Button dynamicAction = findViewById(R.id.dynamicAction);
        dynamicAction.setOnClickListener(this);

        //java 代码 来注册 刚刚的接受者即可
        //第二步,在onCreate注册广播
        //动态使用Java代码注册一个广播接受者
        UpdateDynamicReceiver updateDynamicReceiver = new UpdateDynamicReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ActionUtils.DYNAMIC_ACTION);
        registerReceiver(updateDynamicReceiver, filter);
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.staticAction:
                staticReceiver();
                break;

            case R.id.dynamicAction:
                dynamicAction();
                break;

            default:
                break;
        }
    }

    //第三步:动态发送给接受者
    private void dynamicAction() {
        Intent intent = new Intent();
        intent.setAction(ActionUtils.DYNAMIC_ACTION);
        sendBroadcast(intent);
    }

    //第二步,发送给接受者
    //静态发送广播,给接受者
    private void staticReceiver() {
        Intent intent = new Intent();
        //STATIC_ACTION,与注册时一致
        intent.setAction(ActionUtils.STATIC_ACTION);
        sendBroadcast(intent);

    }
}
------------------------------------------------------------
    //静态:

    /**
 * @date : 2021/10/17 19:00
 * 接受者
 */

    public class CustomerReceiver extends BroadcastReceiver {


        private static final String TAG = "CustomerReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {

            Log.d(TAG, "CustomerReceiver onReceive");

        }
    }
---------------------------------------------------------------
    //动态

    /**
 * @date : 2021/10/17 19:25
 * 第一步:定义广播接受者
 */

    public class UpdateDynamicReceiver extends BroadcastReceiver {
        private static final String TAG = "UpdateDynamicReceiver";

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "onReceive: ");
        }
    }   

四.常用框架

1.热修复

1.什么是热修复

image.png

2.Thinker

..........................

3.okHttp

1.基本使用

image.png

implementation 'com.squareup.okhttp3:okhttp:4.9.0'

声明权限   
<uses-permission android:name="android.permission.INTERNET"/>
main_layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="okHttp!"
        android:textSize="30sp" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="getSyn"
        android:text="get同步" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="getASyn"
        android:text="get异步" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="postSyn"
        android:text="post同步" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="post异步"
        android:onClick="postASyn"/>
</LinearLayout>

///Java文件
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private OkHttpClient okHttpClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        okHttpClient = new OkHttpClient();
    }

    //同步
    public void getSyn(View view) {
        new Thread() {
            @Override
            public void run() {
                Request request = new Request.Builder()
                        .url("https://www.httpbin.org/get?a=1&b=2").build();

                //准备好请求的call对象
                Call call = okHttpClient.newCall(request);
                try {
                    Response response = call.execute();
                    Log.w(TAG, "getSyn: " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    //异步
    public void getASyn(View view) {
        Request request = new Request.Builder()
                .url("https://www.httpbin.org/get?a=1&b=2").build();

        //准备好请求的call对象
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {

            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                if (response.isSuccessful()) {
                    Log.w(TAG, "getASyn: " + response.body().string());
                }
            }
        });
    }

    //同步
    public void postSyn(View view) {
        new Thread() {
            @Override
            public void run() {
                //创建请求头
                FormBody formBody = new FormBody.Builder()
                        .add("a", "1").add("b", "2").build();

                Request request = new Request.Builder()
                        .url("https://www.httpbin.org/post").post(formBody).build();

                Call call = okHttpClient.newCall(request);
                try {
                    Response response = call.execute();
                    Log.w(TAG, "postSyn: " + response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    //异步
    public void postASyn(View view) {
        //创建请求头
        FormBody formBody = new FormBody.Builder()
                .add("a", "1").add("b", "2").build();

        Request request = new Request.Builder()
                .url("https://www.httpbin.org/post").post(formBody).build();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {

            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                Log.w(TAG, "postASyn: " + response.body().string());
            }
        });
    }
}

2.post请求的数据编码

image.png

3.okhttp配置

1.拦截器

前置:OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor()){}

后置:OkHttpClient okHttpClient = new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor()){}

//添加拦截器
        OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
            @NonNull
            @Override
            public Response intercept(@NonNull Chain chain) throws IOException {
                //前置处理
                Request request = chain.request().newBuilder().addHeader("os", "android")
                        .addHeader("version", "1.0").build();
                Response response = chain.proceed(request);
                //后置处理
                return response;
            }
        }).build();

2.缓存

OkHttpClient okHttpClient = new OkHttpClient.Builder().cache(
        new Cache(new File("D:cache/test",100*1024*1024))).build;

3.cookie

 @Test
    public void cookieTest() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .cookieJar(new CookieJar() {
                    @Override
                    public void saveFromResponse(@NonNull HttpUrl httpUrl, @NonNull List<Cookie> list) {
                        cookies.put(httpUrl.host(), list);
                    }
                    @NonNull
                    @Override
                    public List<Cookie> loadForRequest(@NonNull HttpUrl httpUrl) {
                        List<Cookie> cookies = CookieTest.this.cookies.get(httpUrl.host());
                        return cookies == null ? new ArrayList<>() : cookies;
                    }
                })
                .build();
        FormBody formBody = new FormBody.Builder().add("username", "17530588817")
                .add("password", "123456").build();
        Request request = new Request.Builder()
                .url("https://www.wanandroid.com/user/login").post(formBody).build();
        Call call = okHttpClient.newCall(request);
        try {
            Response response = call.execute();
            System.out.println(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.Gson

google提供的json操作框架

注:

1.如果对象里的属性为null,gson序列化是会忽略该属性,但是在list,set等数据结构中不会忽略

2.@Expose注解,可以设置默认序列化的true和false

1.Java对象的系列化和反序列化

@Test
    public void testObject() {
        Student student = new Student("划水", 18, 1001);
        Job job = new Job("新时代农民工", 15000);
        student.setJob(job);
        Gson gson = new Gson();

        String sJson = gson.toJson(student);
        System.out.println("序列化: " + sJson);

        Student fromJson = gson.fromJson(sJson, Student.class);
        System.out.println("反序列化:" + fromJson);
    }

2.数组、列表、Map序列化和反序列化

// 数组序列化 
@Test
    public void testArray() {
        Student[] students = new Student[3];
        students[0] = new Student("摸鱼", 50, 1001);
        students[1] = new Student("起飞", 42, 1002);
        Gson gson = new Gson();
        String toJson = gson.toJson(students);
        System.out.println("序列化:" + toJson);
        Student[] studentsFromGson = gson.fromJson(toJson, Student[].class);
        System.out.println("反序列化:" + Arrays.toString(studentsFromGson));
    }
---------------------------------------------------------------------
// 列表序列化
@Test
    public void testList() {
        List<Student> list = new ArrayList<>();
        list.add(new Student("划水", 12, 1001));
        list.add(new Student("摸鱼", 43, 1002));
        list.add(new Student("抓虾", 20, 1003));
        list.add(null);
        Gson gson = new Gson();
        String s = gson.toJson(list);
        System.out.println("序列化:" + s);
        Type type = new TypeToken<List<Student>>() {
        }.getType();
        List<Student> fromJson = gson.fromJson(s, type);
        System.out.println("反序列化1:" + fromJson.get(0));
        System.out.println("反序列化2:" + fromJson.get(1));
        System.out.println("反序列化3:" + fromJson.get(2));
        System.out.println("反序列化4:" + fromJson.get(3));
    }
----------------------------------------------------------------------
//map
    @Test
    public void testMap() {
        HashMap<String, Student> maps = new HashMap<>();
        maps.put("1",new Student("划水",12,1001));
        maps.put("2",new Student("摸鱼",52,1002));
        maps.put("3",new Student("高情商",55,1003));
        maps.put("4",null);
        Gson gson = new Gson();
        String json = gson.toJson(maps);
        System.out.println("序列化:" + json);
        //定义类型
        Type type = new TypeToken<Map<String, Student>>() {
        }.getType();
        Map<String,Student> fromJson = gson.fromJson(json, type);
        System.out.println("序列化1:" + fromJson.get("2"));
        System.out.println("序列化2:" + fromJson.get("4"));
    }

待续 ......