首先实在Main activity中的onCreate()方法
调用读取登录信息的方法
appContext.initLoginInfo();
这个appContext是一个Context实例appContext = (AppContext)
getApplication();
所以这里不要纠结。
我们打开initLoginInfo()方法看看
public void initLoginInfo() {
User loginUser = getLoginInfo();
if(loginUser!=null &&
loginUser.getUid()>0
&& loginUser.isRememberMe()){
this.loginUid = loginUser.getUid();
this.login = true;
}else{
this.Logout();
}
}
其中这个User是用户信息的bean类
这里做的如下判断,用户信息不为空,用户的Uid大于零,用户配置了记住登录
我们看下getLoginInfo()里面做了什么
public User getLoginInfo() {
User lu = new User();
lu.setUid(StringUtils.toInt(getProperty("user.uid"), 0));
lu.setName(getProperty("user.name"));
lu.setFace(getProperty("user.face"));
lu.setAccount(getProperty("user.account"));
lu.setPwd(CyptoUtils.decode("oschinaApp",getProperty("user.pwd")));
lu.setLocation(getProperty("user.location"));
lu.setFollowers(StringUtils.toInt(getProperty("user.followers"),
0));
lu.setFans(StringUtils.toInt(getProperty("user.fans"), 0));
lu.setScore(StringUtils.toInt(getProperty("user.score"),
0));
lu.setRememberMe(StringUtils.toBool(getProperty("user.isRememberMe")));
return lu;
}
StringUtils.toXX()系列方法就是进行数据类型转换,我们这里忽略它的影响,看来拿到登录信息就是靠这个方法的getProperty(String
key)这个方法
那我们导航进去看看
这个方法是AppContext. getProperty(String key)
这个AppContext是继承Application类的全局类。
这是getProperty(String key的实现
public String getProperty(String key){
return AppConfig.getAppConfig(this).get(key);
}
这里只是利用上下文变量对AppConfig进行初始化
public static AppConfig getAppConfig(Context context) {
if (appConfig == null) {
appConfig = new AppConfig();
appConfig.mContext = context;
}
return appConfig;
}
接着调用AppConfig的get(String key)方法
下面打开 用AppConfig的get(String key)方法
public String get(String key) {
Properties props = get();
return (props != null) ? props.getProperty(key) : null;
}
这个是调用的get()方法,我们根据注释了解一下
public Properties get() {
FileInputStream fis = null;
// 一种继承自HashTable的数据结构
Properties props = new Properties();
try {
// 读取files目录下的config
// fis = activity.openFileInput(APP_CONFIG);
// 读取app_config目录下的config
File dirConf = mContext.getDir(APP_CONFIG,
Context.MODE_PRIVATE);
fis = new FileInputStream(dirConf.getPath() + File.separator
+ APP_CONFIG);
props.load(fis);
} catch (Exception e) {
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
return props;
}
关键就在于这个类了Properties,这是java.lang.Properties中的一个类常用来做配置文件,上述操作读取的是/data/data/应用包名/app_config
目录下的config文件,如下图是在File Explorer打开的目录。
之前我学到的做法是将用户信息保存在sharedPreferences中,然后每次打开应用就读取登录信息,然而开源中国客户端的做法,却是很是特别。
可以用一些软件打开这个config文件(我用浏览器打开的),可以看到这一系列的能过户信息
#Sun Jul 05 08:42:29 GMT 2015
cookie=oscid\=Ws5aACwl+tjuXgd72zzwyfbh8wFSTqiLRYeTiUsndtqzRShHS7j6OgJWtGq/XwP6j8bN2/Xud+FyLYF+t6YsMj3/VY1/LtnH4yFzcv+eK1h56tNAVvulFw==;
save_image_path=/storage/emulated/0/OSChina/
user.score=0
user.name=\u8c22\u6587\u5fe0
user.account=wumengpiaoluo@163.com
user.uid=2282838
user.followers=1
user.face=2282838_100.jpg?t\=1417487687000
user.location=\u5e7f\u4e1c \u5e7f\u5dde
user.isRememberMe=true
APP_UNIQUEID=70740b81-b7b1-449f-b667-8051eaa6b366
user.pwd=1C6E1E50080CB1D121D0B4EDCB4203FE
user.fans=0
所以实际上通过查看Properties的源码可以知道,其实它就是把配置信息按照键值对的方式读取出来。我们简单看下Properties中的源码,主要是这个load(Reader
reader)方法
public class Properties extends Hashtable{
……………
@SuppressWarnings("fallthrough")
public synchronized void load(Reader in) throws IOException
{
if (in == null) {
throw new NullPointerException();
}
int mode = NONE, unicode = 0, count = 0;
char nextChar, buf[] = new char[40];
int offset = 0, keyLength = -1, intVal;
boolean firstChar = true;
BufferedReader br = new BufferedReader(in);
while (true) {
intVal = br.read();
if (intVal == -1) {
break;
}
nextChar = (char) intVal;
if (offset == buf.length) {
char[] newBuf = new char[buf.length * 2];
System.arraycopy(buf, 0, newBuf, 0, offset);
buf = newBuf;
}
if (mode == UNICODE) {
int digit = Character.digit(nextChar, 16);
if (digit >= 0) {
unicode = (unicode << 4) +
digit;
if (++count < 4) {
continue;
}
} else if (count <= 4) {
throw new IllegalArgumentException("Invalid Unicode sequence:
illegal character");
}
mode = NONE;
buf[offset++] = (char) unicode;
if (nextChar != '\n') {
continue;
}
}
if (mode == SLASH) {
mode = NONE;
switch (nextChar) {
case '\r':
mode = CONTINUE; // Look for a following \n
continue;
case '\n':
mode = IGNORE; // Ignore whitespace on the next line
continue;
case 'b':
nextChar = '\b';
break;
case 'f':
nextChar = '\f';
break;
case 'n':
nextChar = '\n';
break;
case 'r':
nextChar = '\r';
break;
case 't':
nextChar = '\t';
break;
case 'u':
mode = UNICODE;
unicode = count = 0;
continue;
}
} else {
switch (nextChar) {
case '#':
case '!':
if (firstChar) {
while (true) {
intVal = br.read();
if (intVal == -1) {
break;
}
nextChar = (char) intVal;
if (nextChar == '\r'
nextChar == '\n') {
break;
}
}
continue;
}
break;
case '\n':
if (mode == CONTINUE) { // Part of a \r\n sequence
mode = IGNORE; // Ignore whitespace on the next line
continue;
}
// fall into the next case
case '\r':
mode = NONE;
firstChar = true;
if (offset > 0
(offset == 0 && keyLength == 0))
{
if (keyLength == -1) {
keyLength = offset;
}
String temp = new String(buf, 0, offset);
put(temp.substring(0, keyLength), temp
.substring(keyLength));
}
keyLength = -1;
offset = 0;
continue;
case '\\':
if (mode == KEY_DONE) {
keyLength = offset;
}
mode = SLASH;
continue;
case ':':
case '=':
if (keyLength == -1) { // if parsing the key
mode = NONE;
keyLength = offset;
continue;
}
break;
}
if (Character.isWhitespace(nextChar)) {
if (mode == CONTINUE) {
mode = IGNORE;
}
// if key length == 0 or value length == 0
if (offset == 0
offset == keyLength
mode == IGNORE) {
continue;
}
if (keyLength == -1) { // if parsing the key
mode = KEY_DONE;
continue;
}
}
if (mode == IGNORE
mode == CONTINUE) {
mode = NONE;
}
}
firstChar = false;
if (mode == KEY_DONE) {
keyLength = offset;
mode = NONE;
}
buf[offset++] = nextChar;
}
if (mode == UNICODE && count
<= 4) {
throw new IllegalArgumentException("Invalid Unicode sequence:
expected format \\uxxxx");
}
if (keyLength == -1 && offset
> 0) {
keyLength = offset;
}
if (keyLength >= 0) {
String temp = new String(buf, 0, offset);
String key = temp.substring(0, keyLength);
String value = temp.substring(keyLength);
if (mode == SLASH) {
value += "\u0000";
}
put(key, value);
}
}
……………
}
在这个方面里面主要是对编码方式进行判断,然后将属性按照键值对形式存储。
(具体还得研究一下这个Properties的具体实现原理,这里暂时忽略)