实验五:基于文件的日程安排
一、实验目的
1. 掌握首选项方式的存储和读取。
2. 掌握位于内存上的数据文件的存储和读取
3. 掌握位于SD卡上的数据文件的存储和读取
二、实验内容
实现基于文件的日程安排应用,运行结果如图所示。通过单击增加图标打开新增活动界面,通过单击保存按钮将活动内容写入到文件,并返回前页。
三、理论
根据实验内容及要求,将涉及到的相关理论方面的知识点在此处列举一下。
用户首选项信息是以键值对的形式存放在应用中的XML文件中,用于保存程序配置信息等少量数据。Android提供了SharedPreferences 类及相关的一系列方法来操作和处理这些数据信息。数据文件也可以保存在机身内存或者SD卡中,Android 数据文件的读写操作采用了FileInputStream类和FileOutputStream类,以及相关的一系列方法。
四、设计步骤
将设计内容细化为具体步骤,完善每步的具体内容。
- 修改主布局如下所示,请将下列空出代码部分补全。
- 修改主Activity文件,通过getItemList()方法从文件item中读取数据显示到ListView组件中。单击新增打开增加活动界面,新增活动界面关闭返回时在onActivityResult()方法中再次调用getItemList()方法获取最新数据并显示,代码如下:
- 创建增加活动界面布局文件additem.xml,请将下列空出代码部分补全。
- 创建增加活动界面Activity文件中AddItemActivity.java,输入新增活动的日期、开始时间、结束时间、活动名称,保存到文件item中,代码如下所示。
- 在AndroidManifest.xml文件中添加新赠活动界面的标记,代码如下所示。
运行本实例,完成结果,另请增加修改和删除功能。
五、效果图展示
根据实验内容的要求,把设计的每部分效果图进行展示,并对核心代码进行分析。(此处需要截图)
六、实验总结
此处是对本次实验过程的总结(主要学习到了哪些知识,有什么心得体会等)。
七、Tips
上面的字都是L文忠哥哥码的❤, L文忠哥哥是好人。
还有老师让写的报告是效果图展示加上核心代码,大家看着来就行。
接着说一些可能会用到的操作吧
这里是修改背景颜色的
#FFC0CB 是粉色😀
各种颜色可以参考这个大佬的博客
https://blog.csdn.net/wadyloo/article/details/77871865
大家自行设置就行。
这一题大家注意设置正确的命名
新建空活动时,他每次会帮你自动命名,实验上起了个自己的名字,大家记得修改啊。
八、代码
activity_main.xml
<?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"
android:background="#fffae4"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/title"
android:background="#aaffe8"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="已安排活动"
android:textSize="40dp"
/>
<ListView
android:layout_marginTop="50dp"
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:layout_width="80dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:src="@drawable/send"
android:onClick="add"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
MainActivity.java
package com.example.test3;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView itemList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemList = (ListView) findViewById(R.id.listView);
getItemList();
}
private void getItemList() {
ArrayList<String> list = new ArrayList<String>();
try {
FileInputStream in = openFileInput("item");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = "";
while((line = br.readLine()) != null) {
list.add (line) ;
}
br.close();
in.close();
String[] contents= {};
String[] allItem = list.toArray(contents);//将动态数组转化为字符串数组
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, allItem);
itemList.setAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
public void add(View view) {
Intent intent = new Intent (MainActivity.this, AddItemActivity.class);
startActivityForResult(intent, 0x111);//打开新界面
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0x111 && resultCode == 0x111) {
getItemList();
}
}
}
additem.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:background="#fffae4"
android:orientation="vertical"
tools:context=".AddItemActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="新增活动"
android:textSize="40dp"
android:gravity="center_horizontal"
android:background="#aaffe8"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="日期"
android:textSize="30dp"
/>
<EditText
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="chooseDate"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始时间"
android:textSize="30dp"
/>
<EditText
android:id="@+id/startTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="chooseStartTime"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="结束时间"
android:textSize="30dp"
/>
<EditText
android:id="@+id/endTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="chooseEndTime"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="活动说明"
android:textSize="30dp"
/>
<EditText
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<Button
android:id="@+id/save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="save"
android:text="保存"
/>
</LinearLayout>
AddItemActivity.java
package com.example.test3;
import androidx.appcompat.app.AppCompatActivity;
import android.app.DatePickerDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TimePicker;
import android.widget.Toast;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class AddItemActivity extends AppCompatActivity {
private EditText date, startTime, endTime, item;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.additem);
date = (EditText) findViewById(R.id.date);
startTime = (EditText) findViewById(R.id.startTime);
endTime = (EditText) findViewById(R.id.endTime);
item = (EditText) findViewById(R.id.item);
}
public void chooseDate(View view) {
DatePickerDialog datePickerDialog = new DatePickerDialog(AddItemActivity.this, new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker datePicker, int i, int i1, int i2) {
date.setText(i+"-"+(i1+1)+"-"+i2);
}
}, 2013, 8, 20);
datePickerDialog.setMessage("请选择结束时间");
datePickerDialog.show();
}
public void chooseStartTime(View view) {
TimePickerDialog timePickerDialog = new TimePickerDialog(AddItemActivity.this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int i, int i1) {
startTime.setText(i+":"+i1);
}
}, 10, 0, true);
timePickerDialog.setMessage("请选择开始时间");
timePickerDialog.show();
}
public void chooseEndTime(View view) {
TimePickerDialog timePickerDialog = new TimePickerDialog(AddItemActivity.this, new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker timePicker, int i, int i1) {
endTime.setText(i+":"+i1);
}
}, 10, 0, true);
timePickerDialog.setMessage("请选择结束时间");
timePickerDialog.show();
}
public void save(View view) {
StringBuilder result = new StringBuilder();
result.append(date.getText().toString()+" ");
result.append(startTime.getText().toString()+"-");
result.append(endTime.getText().toString()+" ");
result.append(item.getText().toString());
try {
FileOutputStream out = openFileOutput("item", MODE_APPEND);
PrintStream ps= new PrintStream(out);
ps.println(result.toString());
ps.close();
out.close();
Toast.makeText(this, "保存完毕!", Toast.LENGTH_LONG).show();
Intent intent = getIntent();
setResult(0x111, intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Test3"
tools:targetApi="31">
<activity
android:name=".AddItemActivity"
android:label="@string/app_name"
android:exported="false">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application>
</manifest>
续
因为解释起来很麻烦所以删除和修改的功能没有加以完善,今天得空来整理一下吧。我们想要对文件里的一些日程信息进行删除但其实文件里并不是将日程独立开来的,而是将所有日程拼接成字符串存储。我们想对文件里的数据进行删除操作的话我们就可以先将日程读入到数组里,然后在数组里进行删除操作,接下来我们来了解一下操作
FileOutputStream out = openFileOutput(“item”, MODE_APPEND);
FileOutputStream out = openFileOutput(“item”, MODE_PRIVATE);
这里MODE_APPEND是向文件里追加元素的意思,而MODE_PRIVATE是将原文件覆盖掉,而文件文件我们无法直接修改,但是我们可以覆盖。我们将原文件里的日程读入到数组里然后在数组里找到删除然后再把数组里的元素拼接成字符串覆盖文件这不就成功删除元素了嘛(●’◡’●)。
接下来废话少说直接上代码✨
注意一些我进行测试的代码没有删除但是不影响
MainActivity.java
package com.example.test3;
import static androidx.core.content.PackageManagerCompat.LOG_TAG;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView itemList;
private ArrayAdapter<String> mAdapter = null;
private List mList = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
itemList = (ListView) findViewById(R.id.listView);
getItemList();
itemList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String result = parent.getItemAtPosition(position).toString();//获取选择项的值
Toast.makeText(MainActivity.this,"您选中了"+result, Toast.LENGTH_LONG).show();
AlertDialog.Builder adBuilder = new AlertDialog.Builder(MainActivity.this);
adBuilder.setMessage("请你接下来想进行的操作").setNeutralButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) { }
}).setPositiveButton("删除", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "选择了第"+(position+1)+"个进行删除",Toast.LENGTH_SHORT).show();
/* 注意: 一定要将String[]转成List类型,否则不能动态增加和删除Item */
//mList = new ArrayList<>(Arrays.asList(itemList));
/* 创建适配器实例 */
//mAdapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, mList);
/* 获取ListView布局 */
//itemList = findViewById(R.id.listView);
/* Sets the data behind this ListView */
//itemList.setAdapter(mAdapter);
/* 获取Item内容 */
//String itemStr = (String)parent.getAdapter().getItem(position);
//mAdapter.getItem(position);
//Toast.makeText(MainActivity.this, "你选择了"+itemStr, Toast.LENGTH_SHORT).show();
//Log.d(LOG_TAG, "onItemClick, Item: " + itemStr);
/* 移除Item */
//mAdapter.remove(itemStr);
/* 新添加Item */
//mAdapter.add("New Item: " + itemStr);
//mAdapter.notifyDataSetChanged();
del(position);
Toast.makeText(MainActivity.this, "删除完毕!", Toast.LENGTH_LONG).show();
}
}).setNegativeButton("修改", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "选择了第"+(position+1)+"个进行修改",Toast.LENGTH_SHORT).show();
del(position);
Intent intent = new Intent (MainActivity.this, AddItemActivity.class);
startActivityForResult(intent, 0x111);//打开新界面
getItemList();
}
});
AlertDialog alertDialog = adBuilder.create();
alertDialog.show();
}
});
}
private void del(int position) {
ArrayList<String> list = new ArrayList<String>();
try {
FileInputStream in = openFileInput("item");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = "";
StringBuilder result = new StringBuilder();
while((line = br.readLine()) != null) {
list.add(line);
}
br.close();
in.close();
list.remove(position);
String[] contents= {};
String[] allItem = list.toArray(contents);//将动态数组转化为字符串数组
for(int k=0;k<allItem.length;k++) {
// System.out.println("######"+allItem[k].toString());
result.append(allItem[k].toString());
if(k!=allItem.length-1) {
result.append("\n");
}
}
//Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
FileOutputStream out = openFileOutput("item", MODE_PRIVATE);
PrintStream ps= new PrintStream(out);
ps.println(result.toString());
ps.close();
out.close();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, allItem);
itemList.setAdapter(adapter);
//adapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
private void getItemList() {
ArrayList<String> list = new ArrayList<String>();
try {
FileInputStream in = openFileInput("item");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = "";
while((line = br.readLine()) != null) {
list.add(line);
}
br.close();
in.close();
String[] contents= {};
String[] allItem = list.toArray(contents);//将动态数组转化为字符串数组
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, allItem);
itemList.setAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
public void add(View view) {
Intent intent = new Intent (MainActivity.this, AddItemActivity.class);
startActivityForResult(intent, 0x111);//打开新界面
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0x111 && resultCode == 0x111) {
getItemList();
}
}
}
这里用到了关于弹窗方面的知识,修改我为了简单就把修改定义为删除后再次打开页面进行追加,其实可以继续用数组存储然后打开页面重新设定数据传回来然后更新数组最后再把数组内容拼接字符串覆盖文件。大家可以尝试一下吧!溜了溜了~~~~~~~~~~~~~~~~~~~~~