文章目录
5.1 数据存储方式
Android平台提供五种存储方式:
- 文件存储
- SharedPreferences存储:存储一些简单的配置信息的一种机制,采用XML格式将数据存储到设备中,通常用于存储配置信息,如用户名密码等
- SQLite数据库存储:一个轻量级数据库,运算速度快,占用内存小,支持基本SQL语法,一般作为复杂数据的存储引擎,可以存储用户信息等
- ContentProvider:是Android四大组件之一,主要用于应用程序之间的数据交换,可以将自己的数据共享给其他的应用程序使用
- 网络存储:网络存储需要将Android网络数据包打交道,将数据存储在服务器上,通过网络存储空间来存储获取信息
5.2 文件存储
文件存储与Java中的文件存储类似,通过I/O流的形式把数据直接存储到文件中
5.2.1 将数据存入到文件中
数据存入到文件中,有两种存储方式:内部存储和外部存储
内部存储
内部存储是将应用程序的数据以文件的形式存储到应用程序中(路径默认在data/data/),此时存储的文件会被所在的应用程序私有化,其他软件想要操作本应用程序中的文件,则需要申请权限,当创建的应用程序被卸载的时候,这里的数据也会随之被清除
实例代码如下:
FileOutputStream fos = openFileOutput(String name,int mode);//输出到文件
FileInputStream fis = openFileInput(String string);//读取文件
mode代表文件的操作模式:
-
MODE_PRIVATE:只能被应用程序读写
-
MODE_APPEND:该文件的内容可以追加
-
MODE_WORLD_READABLE:该文件的内容可以被其他程序读
-
MODE_WORLD_WRITEABLE:改文件的内容可以被其他程序写
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String filename = "data.txt";
String content = "hello world";
FileOutputStream fos =null;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);//打开
fos.write(content.getBytes());//写入
Toast.makeText(MainActivity.this,"yes",Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fos!=null)
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
外部存储
顾名思义存储到外部设备上,例如SD卡或者设备内嵌的存储卡,外部存储可以被其他应用程序读取,所以这种方式并不安全
因为外部设备可以会被移除,所以要先确认外部设备是否可用,当外部设备具有读写权限的时候,就可以通过FileOutputStream,FileInputStream来读写文件
实例代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String state = Environment.getExternalStorageState();
if(state.equals(Environment.MEDIA_MOUNTED))
{
File SDPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);//获取到downloads路径,此方法在新版本中似乎被弃用
File path = Environment.getDataDirectory();
File file = new File(SDPath,"data.txt");
String data = "hello world";
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(data.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fos!=null)
{
fos.close();
}
}catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
![Screenshot_20220412-232216_Google_文件极客](https://mhduiy-1310556463.cos.ap-chongqing.myqcloud.com/img/Screenshot_20220412-232216_Google_%E6%96%87%E4%BB%B6%E6%9E%81%E5%AE%A2.png)
5.2.2 从文件中读取数据
读取内部存储中的数据
woc,是不是那些毒瘤那么大是不是因为把数据存到了这个地方,导致删都无法删除,这里的文件通过简单的方法是读取不了的
实例代码
//前提是已经在内部存储区域创建好了文件
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String content = "";
FileInputStream fis =null;
try {
fis = openFileInput("data.txt");
byte[] buffer = new byte[fis.available()];//创建缓冲区,获取文件的长度,数组的大小
fis.read(buffer);//读取到buffer
content = new String(buffer);//转为String
}catch (Exception e)
{
e.printStackTrace();
}finally {
try {
if(fis!=null)
{
fis.close();
}
}catch (IOException e)
{
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this,content,Toast.LENGTH_LONG).show();//输出
}
}
//最后输出结果为hello world
读取外部存储文件中的数据
实例代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File SDPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File file = new File(SDPath,"data.txt");
FileInputStream fis = null;
BufferedReader br =null;
String data = "";
try {
fis = new FileInputStream(file);
br = new BufferedReader(new InputStreamReader(fis));
data = br.readLine();
}catch (Exception e)
{
e.printStackTrace();
}finally {
try {
if(br!=null)
br.close();
}catch (IOException e)
{
e.printStackTrace();
}
try {
if(fis!=null)
fis.close();
}catch (IOException e)
{
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this,data,Toast.LENGTH_LONG).show();
}
}
申请SD卡读取权限
为了保证应用程序的安全性,Android规定,当程序访问一些关键信息的时候,必须申请权限,根据Android SDK版本的不同,权限的申请分为两种方式,分别为静态申请权限和动态申请权限
-
静态申请(Android SDK 6.0以下)
在清单文件中加入
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-
动态申请Android SDK 6.0以上)
6.0以后权限分为正常权限和危险权限(包括:位置,日历,相机,联系人,存储卡,麦克风,电话,短信)
申请正常权限与静态权限相同,申请危险权限的时候除了需要在清单文件中申请,还需要再代码中静态申请
ActivityCompat.requestPermissions(MainActivity.this,new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"},1);
-
当用户单击申请权限的提示框的允许的时候,程序会回调执行
onRequestPermissonsResult()
方法@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==1) { for(int i=0;i<permissions.length;i++) { if(permissions[i].equals("android.permission.WRITE_EXTERNAL_STORAGE")&&grantResults[i]== PackageManager.PERMISSION_GRANTED) { Toast.makeText(this,"申请成功",Toast.LENGTH_LONG).show(); } else { Toast.makeText(this,"申请失败",Toast.LENGTH_LONG).show(); } } } }
5.3 SharedPreferences存储
这种存储方式相对简单,主要用于存储账号和密码等简单信息,采用键值对的形式进行存储
示例代码
SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();//获取编辑器,data代表文件名
editor.putString("name","张三");//存储String类型数据
editor.putInt("age",18);//存储int类型数据
editor.commit();//提交数据,必须执行此操作,否则改动不起作用
SharedPreferences sp1 = getSharedPreferences("data",MODE_PRIVATE);
String data = sp.getString("name","未找到数据");//第一个参数代表key第二个参数代表缺省值,不存在key的时候就返回缺省值
editor.remove("name");//删除key=name的数据
editor.clear();//删除所有数据
5.4 SQLite数据库存储
SQLite可以存储大量数据,并且可以对数据进行管理和维护
5.4.1 SQLite数据库的创建
创建SQLite数据库只需要创建一个继承SQLiteOpenHelper类的子类,重写onCreat()方法和onUpgrade()方法
示例代码
class MyHelper extends SQLiteOpenHelper
{
public MyHelper(Context context)//必须调用父类的构造方法
{
super(context,"itcast.db",null,2);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20),price INTEGER)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
调用父类的构造方法的时候,传入的参数分别是:上下文对象,数据库名称,游标工厂(通常是null)数据库版本
重写的onCreate()方法在创建的时候调用,通常用于初始化数据库,重写的onUpgrade()方法在数据库版本号升级的时候调用
5.4.2 SQLite数据库的基本操作
新增数据
以数据库,itcast的表information为例
示例代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyHelper helper = new MyHelper(this);
SQLiteDatabase db = helper.getWritableDatabase();//获取读写对象
ContentValues contentValues = new ContentValues();//可以存储键值对
contentValues.put("name","张三");//数据传入
contentValues.put("price","200");
long id = db.insert("information",null,contentValues);//插入数据到数据据中
db.close();//关闭数据库
}
}
需要注意的是,使用完SQLiteDatabase对象后一定要调用close()方法关闭与数据库的连接,否则数据库的连接会一直存在,不断消耗资源,当内存不足的时候就会获取不到SQLiteDatabase对象,并且会报出数据库未关闭的异常
删除数据
SQLiteDatabase db = helper.getWritableDatabase();//获取读写对象
int num = db.delete("information","_id=?",new String[]{id+""});
db.close();
修改数据
SQLiteDatabase db = helper.getWritableDatabase();//获取读写对象
ContentValues contentValues = new ContentValues();//可以存储键值对
value.put("price",price);
int number = dp.update("information",values,"name =?",new String[]{name});
db.close();
update( )的参数:第一个参数代表数据库表的名称,第二个参数表示新数据,第三个参数表示修改的数据的查找条件,第四个参数表示查找条件的参数
查询数据
public void find(int id)
{
MyHelper helper = new MyHelper(MainActivity.this);
SQLiteDatabase db = helper.getReadableDatabase();
Cursor cursor = db.query("information",null,"_id=?",new String[]{id+""},null,null,null);
if(cursor.getCount()!=0)//当数据数量不等于0的时候,进入读取循环
{
while(cursor.moveToNext())
{
@SuppressLint("Range") String _id = cursor.getString(cursor.getColumnIndex("_id"));
@SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex("name"));
@SuppressLint("Range") String price = cursor.getString(cursor.getColumnIndex("price"));
}
}
cursor.close();//关闭Cursor(游标)对象,非常必要,原因与数据库连接的差不多
db.close();
}
query()的七个参数:
- 数据库表的名称
- 查询的列名
- 接受查询条件的子句
- 接受查询子句对应的条件值
- 表示分组方式
- 接受having条件(定义组的过滤器)
- 表示排序方式
使用SQL语句对数据库进行操作
在使用SQLite数据库的时候除了上述方法,还可以使用execSQL( )方法通过SQL语句进行操作,示例代码如下
db.execSQL("insert into information (name ,price) value (?,?)",new Object[]{name,price});//增加
db.execSQL("delete from information where price =?");//删除
db.execSQL("update information set name=? where price =?",new Object[]{name,price});//修改
Cursor cursor = sb.rawQuery("select * from information whrer name =?",new String[]{name});//查询,采用此方法会返回一个结果集
5.4.3 SQLite数据库中的事务
数据库事务是一个对数据库执行工作单元,是针对数据库的一组操作,他可以由一条或者多条SQL语句组成,事务是以逻辑顺序完成的工作单位或序列,可以由用户手动操作完成,也可以由某种数据库程序自动完成
事务的操作比较严格,他必须包括ACID,ACID是指数据库事务正确执行的的四个基本要素的缩写,这四个要素分别是
- 原子性:表示事务是一个不可以再分割的工作单位,事务中的操作要么全部成功,要么全部回滚
- 一致性:表示事务开始之前和结束之后,数据库的完整性没有被破坏,也就是说数据库事务不能破坏关系数据库的完整性及业务逻辑上的一致性
- 隔离性:表示并发的事务时相互隔离的,也就是一个事务内部操作都必须封装起来,不被其他事务影响到
- 持久性:表示事务一旦提交,该事务对数据做的更改便持久保存在数据库中,并不会被回滚,即使出现了断电等事故,也不会影响数据库中的数据
实例代码
PersonSQLiteOpenHelper = helper = new PersonSQLiteOpenHelper(getApplication());
SQLiteDatabase db = helper.getReadableDatabase();
db.beginTransaction();
try
{
db.execSQL("update person set accont = accont - 1000 where name =?",new Object[]{"张三"});//转出1000
db.execSQL("update information set accont = accont + 1000 where name =?",new Object[]{"王五"});//收入1000
db.setTransactionSucessful();//设置数据库事务处理成功
}catch(Exception e)
{
Log.i("事务处理失败",e.toString())
}finally
{
db.endTransaction();//关闭事务
db.close();
}
需要注意的时:事务操作后一定要关闭事务,如果由事务成功执行的标志,则提交数据,否则数据回滚,最后关闭事务
5.4.4 实战演练-密码管理器
MainActivity.java
bug:mainactivity登录界面未完善
package cn.itcast.myapplication10;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
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.Button;
public class MainActivity extends AppCompatActivity {
Button btn_login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_login = findViewById(R.id.btn_login);
btn_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(MainActivity.this,PWD.class));
}
});
}
}
PWD.java
package cn.itcast.myapplication10;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Vector;
public class PWD extends AppCompatActivity implements View.OnClickListener{
Myhelper myhelper;
private Button mbtn_ser;
private Button mbtn_re;
private Button mbtn_add;
private Button mbtn_delete;
private Button mbtn_clear;
private Button mbtn_display;
private EditText med_des;
private EditText med_acc;
private EditText med_pwd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pwd);
myhelper = new Myhelper(this);
Init();
}
void Init()
{
mbtn_ser = findViewById(R.id.btn_search);
mbtn_add = findViewById(R.id.push);
mbtn_re = findViewById(R.id.btn_re);
mbtn_delete = findViewById(R.id.btn_delete);
mbtn_clear = findViewById(R.id.btn_clear);
mbtn_display = findViewById(R.id.btn_display);
med_des = findViewById(R.id.ed_des);
med_acc = findViewById(R.id.ed_accont);
med_pwd = findViewById(R.id.ed_pwdd);
mbtn_ser.setOnClickListener(this);
mbtn_add.setOnClickListener(this);
mbtn_re.setOnClickListener(this);
mbtn_delete.setOnClickListener(this);
mbtn_clear.setOnClickListener(this);
mbtn_display.setOnClickListener(this);
}
@Override
public void onClick(View view) {
String describtion,account,password;
SQLiteDatabase db;
ContentValues values;
switch (view.getId())
{
case R.id.btn_search://查询
describtion = med_des.getText().toString();
med_acc.setText("");
med_pwd.setText("");
if(TextUtils.isEmpty(describtion))
{
Toast.makeText(PWD.this,"填写描述开始查询",Toast.LENGTH_LONG).show();
return;
}
db = myhelper.getReadableDatabase();
Cursor cursor = db.query("information",null,null,null,null,null,null);
if(cursor.getCount()==0) {
Toast.makeText(PWD.this, "表为空", Toast.LENGTH_LONG).show();
db.close();
cursor.close();
return;
}
else
{
cursor.moveToFirst();
do{
if(cursor.getString(3).equals(describtion))
{
med_des.setText(cursor.getString(3));
med_acc.setText(cursor.getString(1));
med_pwd.setText(cursor.getString(2));
}
}while (cursor.moveToNext());
}
if(TextUtils.isEmpty(med_pwd.getText().toString())) {
Toast.makeText(PWD.this, "未找到数据", Toast.LENGTH_LONG).show();
med_des.setText("");
}
cursor.close();
db.close();
break;
case R.id.push://插入
describtion = med_des.getText().toString();
account = med_acc.getText().toString();
password = med_pwd.getText().toString();
if(TextUtils.isEmpty(describtion)||TextUtils.isEmpty(account)||TextUtils.isEmpty(password)) {
Toast.makeText(PWD.this, "上面信息必须填完", Toast.LENGTH_LONG).show();
return;
}
db = myhelper.getReadableDatabase();
Cursor cursor1 = db.query("information",null,null,null,null,null,null);
cursor1.moveToFirst();
if(cursor1.getCount()!=0) {
do {
if (cursor1.getString(3).equals(describtion))//检测重复
{
Toast.makeText(PWD.this, "该描述对应条目已存在", Toast.LENGTH_LONG).show();
med_des.setText("");
med_acc.setText("");
med_pwd.setText("");
cursor1.close();
db.close();
return;
}
} while (cursor1.moveToNext());
}
db = myhelper.getWritableDatabase();
values = new ContentValues();
values.put("describe",describtion);
values.put("account",account);
values.put("pwdd",password);
db.insert("information",null,values);
Toast.makeText(PWD.this,"信息已添加",Toast.LENGTH_LONG).show();
med_des.setText("");
med_acc.setText("");
med_pwd.setText("");
cursor1.close();
db.close();
break;
case R.id.btn_re://修改
boolean flag=false;//是否存在条目
describtion = med_des.getText().toString();
account = med_acc.getText().toString();
password = med_pwd.getText().toString();
if(TextUtils.isEmpty(describtion)||TextUtils.isEmpty(account)||TextUtils.isEmpty(password)) {
Toast.makeText(PWD.this, "上面信息必须填完", Toast.LENGTH_LONG).show();
return;
}
db= myhelper.getWritableDatabase();
values = new ContentValues();
Cursor cursor2 = db.query("information",null,null,null,null,null,null);
cursor2.moveToFirst();
do{
if(cursor2.getString(3).equals(describtion))//检测重复
{
flag=true;
}
}while (cursor2.moveToNext());
if(!flag)
{
Toast.makeText(PWD.this, "没有找到该描述对应条目", Toast.LENGTH_LONG).show();
db.close();
cursor2.close();
return;
}
values.put("account",account);
values.put("pwdd",password);
db.update("information",values,"describe=?",new String[]{describtion});
Toast.makeText(PWD.this, "信息已修改", Toast.LENGTH_LONG).show();
db.close();
cursor2.close();
break;
case R.id.btn_delete://删除
boolean flag1=false;
describtion = med_des.getText().toString();
if(TextUtils.isEmpty(describtion))
{
Toast.makeText(PWD.this, "请填描述以删除", Toast.LENGTH_LONG).show();
return;
}
db = myhelper.getWritableDatabase();
Cursor cursor3 = db.query("information",null,null,null,null,null,null);
cursor3.moveToFirst();
do{
if(cursor3.getString(3).equals(describtion))
{
flag1=true;
}
}while (cursor3.moveToNext());
if(!flag1)
{
Toast.makeText(PWD.this, "没有找到该描述对应条目", Toast.LENGTH_SHORT).show();
db.close();
cursor3.close();
return;
}
db.delete("information","describe=?",new String[]{describtion});
Toast.makeText(PWD.this, "已删除", Toast.LENGTH_LONG).show();
db.close();
cursor3.close();
break;
case R.id.btn_clear:
med_des.setText("");
med_acc.setText("");
med_pwd.setText("");
break;
case R.id.btn_display:
Intent intent = new Intent();
intent.setClass(PWD.this,Display.class);
db= myhelper.getWritableDatabase();
Cursor cursor4 = db.query("information",null,null,null,null,null,null);
ArrayList<String> data=new ArrayList<>();
cursor4.moveToFirst();
if(cursor4.getCount()!=0)
do {
StringBuffer temp = new StringBuffer();
temp.append(cursor4.getString(3)).append('\n');
temp.append(cursor4.getString(1)).append('\n');
temp.append(cursor4.getString(2)).append('\n');
data.add(new String(temp));
}while(cursor4.moveToNext());
intent.putExtra("database",data);//传出数据
startActivity(intent);
db.close();
cursor4.close();
break;
default:
break;
}
}
}
class Myhelper extends SQLiteOpenHelper
{
Myhelper(Context context)
{
super(context,"ittcast.db",null,1);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT ,account VARCHAR(20),pwdd VARCHAR(20),describe VAECHAR(20))");//创建数据库
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Display.java
package cn.itcast.myapplication10;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Vector;
public class Display extends AppCompatActivity {
private TextView view_display;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display);
view_display = findViewById(R.id.dis);
Intent intent = getIntent();
ArrayList<String> temp = new ArrayList<>();
temp = (ArrayList<String>)intent.getSerializableExtra("database");
for(int i=0;i<temp.size();i++)
{
view_display.append("id="+(i+1)+":"+'\n');
view_display.append(temp.get(i));
}
}
}
activity_main.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:layout_margin="20dp"
android:orientation="vertical"
tools:context=".PWD">
<TextView
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:id="@+id/textlogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="少侠请登录"
android:textSize="40dp"
android:textColor="#000000"
android:layout_marginBottom="50dp"/>
<EditText
android:id="@+id/ed_acc"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="账户名:"/>
<EditText
android:id="@+id/ed_pwd"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码:"
android:inputType="textPassword" />
<Button
android:layout_marginTop="50dp"
android:layout_gravity="center"
android:id="@+id/btn_login"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="登录"/>
<Button
android:layout_marginTop="20dp"
android:layout_gravity="center"
android:id="@+id/btn_forget"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="忘记密码"/>
</LinearLayout>
activity_pwd.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:layout_margin="40dp"
android:orientation="vertical"
tools:context=".PWD">
<TextView
android:layout_gravity="center"
android:layout_marginTop="30dp"
android:id="@+id/textlogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(●'◡'●)"
android:textSize="40dp"
android:textColor=" #FF7F50"
android:layout_marginBottom="50dp"/>
<EditText
android:id="@+id/ed_des"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="描述信息:"/>
<EditText
android:id="@+id/ed_accont"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="账户名:"/>
<EditText
android:id="@+id/ed_pwdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="password:"/>
<Button
android:layout_marginTop="30dp"
android:layout_gravity="center"
android:id="@+id/btn_search"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="查询"/>
<Button
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:id="@+id/push"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="录入"/>
<Button
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:id="@+id/btn_re"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="修改"/>
<Button
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:id="@+id/btn_delete"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="删除"/>
<Button
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:id="@+id/btn_clear"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="清除"/>
<Button
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:id="@+id/btn_display"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="全部显示"/>
</LinearLayout>
activity_display.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=".Display">
<TextView
android:id="@+id/dis"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
实例图片