昨天内容拾遗。
一、Activity返回数据的时候有三种情况
二、Java异常分类
一、Activity返回数据的时候有三种情况:
(1)正确返回,resultCode是有值的。这个值是我们指定的一个数据。
(2)通过返回键实现,resultCode中没有我们需要的数据。
(3)异常返回,打开的Activity发生异常。此时Activity自动关闭,resultCode没有数据。
二、Java异常分类:
(1)CheckExceotion编译时异常,这种情况下必须处理异常。通过throws将异常抛出,通过try-catch处理异常。
还有一种方式
try
{}
catch(Exception ex)
{
throwException(ex);
}
(2)RuntimeException运行时异常。这种异常可以不用处理。
(3)NullPointerException控件没有初始化或者我要找的ID不在我解析的xml文件中。
(4)ClassCastException类型转换失败。在控件初始化的时候我们找的控件和需要的类型不一致。
AlertDialog的按钮本身自带一个关闭的功能。
今天内容:
一、Java反射机制。
二、读写文件
三、使用用户自动登录:
一、Java反射:通过字符串自动查找并加载需要的类和对象。java中提供了解析.class文件的工具。
Field f=dialog.getClass().getSuperClass().getDeclaredField("");
getsuperclass()获取父类
getDeclaredField获取声明的字段,其中的Field可能是私有的也可能是受保护的,找名为指定字符串的属性。
f.setAccessible(true);
允许操作该属性。
f.set(dialog,flag);
Java中的反射举例。反射可以更改编译的结果。据说反射可以更改final变量。Java反射常用于数据拦截。java中正因为有了反射机制,java语言才真正成为动态语言。
C语言可以直接操作底层硬件,所以黑客常常是C/C++程序员。C#也可以操作硬件。Java语言当中不允许操作底层。
反射举例:
public class Student
{
private String name="neu";
public Student()
{
}
public Student(String name)
{
this.name=name;
}
public void print()
{
if(name.startswith("neu"))
system.out.println("你来自江湖");
else
system.out.println("请你先入江湖");
}
}
public class Test
{
public static void main(String arg[0])
{
Student stu=new Student("eee");
//先找到用的那个class文件,再从class文件中找需要的属性,在更改其中的数据
//cla代表文件出现的位置
Class cla=stu.getClass();
//cla.getFields();查找所有public修饰的属性,该属性可以来自父类
// cla.getDeclaredFields();只查找自身声明的属性,不管那种访问修饰符,返回一个Field字段
//再更改属性
//注意找的时候可能发生意外,名字可能找不到,需要处理异常
try
{
Field f=cla.getDeclaredFields("name");
f.setAccessible(true);
//更改其中的数据
f.set(stu,"aaaa");
Object obj=f.get(stu);
}
catch(Exception e)
{
e.printStackTrace();
}
stu.print();
}
}
该开始输出“你来自江湖”。执行反射后输出“请你先入江湖”。
二、读写文件
Android里操作数据的方式:
(1)保存到数据库(SQLite3)
CRUD:Create、Read、Update、Delete
(2)网络数据库(移动端+web程序(MySQL))
数据库排名:DB2、Oracle、MySQL、SQL Server。
Oracle公司为了打败SQL Server,使MySQL免费。
(3)文件,在手机或存储卡中写一个file文件存储数据。
(4)资源文件,保存一些小数据,通常用来实现一些自动登录。
使用资源文件实现自动登录。能够在Android中写文件和读取资源文件,并实现功能。
资源文件保存在手机的内部存储器中。以XML的格式存储数据。
Android系统基于Linux。Linux编写文件的方式就是Android编写文件的方式。
向文件中添加数据的步骤:
(1)创建SharedPreferences对象,根据操作文件名和操作文件的模式获取SharesPreferences对象。
SharedPreferences sp=getSharedPreferences(name,mode );
第一个参数代表操作的文件名,第二个参数表示打开文件的模式。
mode_private:以私有模式打开。也可以用0来代表。Context.mode_private。
mode_world_readable:说明该资源文件其它程序也可以操作。
mode_world_writeable:说明该资源文件其它程序也可以操作。
mode_append:追加数据,不会发生覆盖。
默认情况下都是mode_private
(2)编辑一个文件要先创建一个文件编辑器,编写文件。编写完了之后提交数据。类似于Windows中的保存。
SharedPreferences.Editor edit=sp.edit();
(3)在编辑器里添加内容。
edit.putString("loginname", "admin");
edit.putInt("age", 20);
如果Key相同,那么Value发生覆盖。和Map相同。
修改:edit.putXxx(key,value);若果key重复会发生覆盖。
删除:edit.remove(key);
(4)保存数据。
edit.commit();
提交数据即保存。
edit.clear();
用于清空数据。
读取资源文件:
(1)创建SharedPreferences对象
SharedPreferences sp=getSharedPreference("文件名",打开模式);
(2)直接获取数据,注意获取数据的类型。
String value=sp.getString(key,defaultvalue); //如果这个值不存在给予一个默认值
三、使用用户自动登录:
(1)创建欢迎页面,在欢迎页面读取资源文件,判断是否需要进入登录页面。
(2)登录页面,在登录成功后把信息写入资源文件。
(3)主页面中显示登录人的信息,可以清除自动登录。
登录页面(LoginActivity.java):
private void setListener()
{
this.btnSubmie.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
// 实现登录验证,固定判断neuedu
String name=editLoginName.getText().toString();
if("neuedu".equals(name))
{
//设置自动登录
if(ckAutoLogin.isChecked())
{
SharedPreferences sp=getSharedPreferences("Login_info", MODE_PRIVATE);
SharedPreferences.Editor edit=sp.edit();
//将登录名和密码写入文件
edit.putString("Login_name", name);
edit.commit();
}
//实现页面跳转
Intent intent=new Intent(LoginActivity.this,MajorActivity.class);
intent.putExtra("user_name", name);
startActivity(intent);
//关闭登录页面
finish();
}
}
});
}
欢迎页面(WelcomeActivity.java):
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sp=getSharedPreferences("login_info", MODE_PRIVATE);
String name=sp.getString("login_name", null);
Intent intent=new Intent();
if(name!=null)
{
if("neuedu".equals(name))
{
//去主页面
intent.setClass(WelcomeActivity.this,MajorActivity.class);
intent.putExtra("user_name", name);
}
else
{
//去登录页面
intent.setClass(WelcomeActivity.this, LoginActivity.class);
}
startActivity(intent);
finish();
}
}
主界面(MajorActivity.java):
private TextView textUserInfo;
private Button btnClear;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_major);
findView();
setListener();
}
private void findView()
{
this.textUserInfo=(TextView) findViewById(R.id.major_tv_user_info);
this.btnClear=(Button) findViewById(R.id.major_btn_clear_suto);
Intent intent=getIntent();
String name=intent.getStringExtra("user_name");
textUserInfo.setText(name);
}
private void setListener()
{
this.btnClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
SharedPreferences sp=getSharedPreferences("login_info",MODE_PRIVATE);
SharedPreferences.Editor edit=sp.edit();
edit.clear();
edit.commit();
}
});
}
Android中读写文件分两种情况:
(1)读取的是当前目录下某个文件中的内容,又叫读取内部存储的文件。
(2)读取SD卡中的文件。
(1)读取的是当前目录下某个文件中的内容,又叫读取内部存储的文件。
通过openFileInputStream("文件名")获取文件流。
通过openFileOutputStream("文件名",模式)获取文件流。
例如:
private TextView textmsg;
private Button btnread;
private Button btnwrite;
private void findView()
{
this.textmsg=(TextView) findViewById(R.id.textView1);
this.btnread=(Button) findViewById(R.id.button1);
this.btnwrite=(Button) findViewById(R.id.button2);
}
private void setListener()
{
this.btnwrite.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
//实现追加模式
try
{
//以追加的方式打开文件
//这是一个二进制的流
FileOutputStream fos=openFileOutput("neu.txt", MODE_APPEND);
String msg="Happy Christmas";
fos.write(msg.getBytes());
fos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
});
this.btnread.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v)
{
//根据读取文件的字节数构建容器
FileInputStream fis;
try
{
fis = openFileInput("neu.txt");
byte[] b=new byte[fis.available()];
//返回值为读取数据的真实个数
int length=fis.read(b);
String msg=new String(b);
textmsg.setText(msg);
fis.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
运行效果:
(2)读手机SD卡
SDcard指的是SD卡或者内置的硬盘。目录是不确定的。
必须要确定SDcard一定可以使用且存在。
Enviroment.getExternalStorageDirectory:获取SDcard的目录
Enciroment getExternalStorageState().equals(Enviroment.MEDIA_MOUNTED)判断SDcard是否存在
SDcard如果存在,根据SDcard的目录去创建或者读取文件。
向SD卡中添加权限,向AndroidManifest.xml中添加权限。向Permisssion中添加权限
比较重要重要的权限:
Android:permission.CALL_PHONE
Android:permission.INTERNET
Android:permission.SMS
Android:permission.WRITE_EXTERNAL_STORAGE
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"/>
例如:
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
File sdcard=Environment.getExternalStorageDirectory();
Date date=new Date();
SimpleDateFormat f=new SimpleDateFormat("yyyy-MM-dd");
String pathname=f.format(date);
File path=new File(sdcard,pathname); //在sdcard下创建pathname名指定的文件
if(!path.exists())
{
path.mkdir();//只创建一级目录
}
File file=new File(path,"test.txt");
try
{
FileOutputStream fos=new FileOutputStream(file,true); //创建文件输出流
String msg="明天考试!!!!";
fos.write(msg.getBytes()); //.write()方法只允许以字符流的形式写入
fos.close();
}
catch (Exception e)
{
e.printStackTrace();
}
附:FileOutputStream中填写true时会在后面添加数据。
if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{
File sdcard=Environment.getExternalStorageDirectory();
File file=new File(sdcard,"/2015-12-23/test.txt");
try
{
FileInputStream fis=new FileInputStream(file);
byte[] b=new byte[fis.available()];
int len=fis.read(b);
fis.close();
String msg=new String(b);
textMsg.setText(msg);
} catch (Exception e)
{
e.printStackTrace();
}
}
附:
如果读取SD卡或文件的时候,SD卡和文件中的内容是中文,输出的时候显示的是乱码,则通过以下方式修改。
String Content=new String(b,"GBK");
在后面添加上编码方式。
文本分页需要确定每一页的显示字符个数。
注意:一个汉字占两个字节。
掌握OnTouch事件。
掌握随机访问流(RandomAccessStream),用于随机访问数据的,可以设置从哪开始读。