Compare commits

...

23 Commits
master ... zy

@ -99,4 +99,5 @@ public class MetaData extends Task {
public int getSyncAction(Cursor c) {
throw new IllegalAccessError("MetaData:getSyncAction should not be called");//传递非法参数异常
}
}

@ -20,32 +20,36 @@ import android.database.Cursor;
import org.json.JSONObject;
/*
*/
public abstract class Node {
public static final int SYNC_ACTION_NONE = 0;
//定义了各种用于表征同步状态的常量
public static final int SYNC_ACTION_NONE = 0;//本地和云端都无可更新内容
public static final int SYNC_ACTION_ADD_REMOTE = 1;
public static final int SYNC_ACTION_ADD_REMOTE = 1;//需要在远程云端增加内容
public static final int SYNC_ACTION_ADD_LOCAL = 2;
public static final int SYNC_ACTION_ADD_LOCAL = 2;//需要在本地增加内容
public static final int SYNC_ACTION_DEL_REMOTE = 3;
public static final int SYNC_ACTION_DEL_REMOTE = 3;//需要在远程云端删除内容
public static final int SYNC_ACTION_DEL_LOCAL = 4;
public static final int SYNC_ACTION_DEL_LOCAL = 4;//需要在本地删除内容
public static final int SYNC_ACTION_UPDATE_REMOTE = 5;
public static final int SYNC_ACTION_UPDATE_REMOTE = 5;//需要将本地内容更新到远程云端
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;
public static final int SYNC_ACTION_UPDATE_LOCAL = 6;//需要将远程云端内容更新到本地
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;
public static final int SYNC_ACTION_UPDATE_CONFLICT = 7;//同步出现冲突
public static final int SYNC_ACTION_ERROR = 8;
public static final int SYNC_ACTION_ERROR = 8;//同步出现错误
private String mGid;
private String mName;
private long mLastModified;
private long mLastModified;//记录最后一次修改时间
private boolean mDeleted;
private boolean mDeleted;//表征是否被删除
public Node() {
mGid = null;

@ -36,6 +36,10 @@ import org.json.JSONObject;
public class SqlData {
/*
TAG
getSimpleName()
*/
private static final String TAG = SqlData.class.getSimpleName();
private static final int INVALID_ID = -99999;
@ -45,6 +49,9 @@ public class SqlData {
DataColumns.DATA3
};
/*
sql5
*/
public static final int DATA_ID_COLUMN = 0;
public static final int DATA_MIME_TYPE_COLUMN = 1;
@ -56,6 +63,7 @@ public class SqlData {
public static final int DATA_CONTENT_DATA_3_COLUMN = 4;
private ContentResolver mContentResolver;
//判断是否直接用Content生成是为turn不是为false
private boolean mIsCreate;
@ -71,10 +79,13 @@ public class SqlData {
private ContentValues mDiffDataValues;
/*
*/
public SqlData(Context context) {
mContentResolver = context.getContentResolver();
mIsCreate = true;
mDataId = INVALID_ID;
mContentResolver = context.getContentResolver();// mContentResolver用于获取ContentProvider提供的数据
mIsCreate = true;//mIsCreate表征当前数据是用哪种方式创建
mDataId = INVALID_ID;//mDataId初始值-99999
mDataMimeType = DataConstants.NOTE;
mDataContent = "";
mDataContentData1 = 0;
@ -82,13 +93,20 @@ public class SqlData {
mDiffDataValues = new ContentValues();
}
/*
*/
public SqlData(Context context, Cursor c) {
mContentResolver = context.getContentResolver();
mIsCreate = false;
mContentResolver = context.getContentResolver();// mContentResolver用于获取ContentProvider提供的数据
mIsCreate = false;//mIsCreate表征当前数据是用哪种方式创建
loadFromCursor(c);
mDiffDataValues = new ContentValues();
}
/*
*/
private void loadFromCursor(Cursor c) {
mDataId = c.getLong(DATA_ID_COLUMN);
mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN);
@ -97,7 +115,11 @@ public class SqlData {
mDataContentData3 = c.getString(DATA_CONTENT_DATA_3_COLUMN);
}
/*
*/
public void setContent(JSONObject js) throws JSONException {
//如果传入的JSONObject对象中有DataColumns.ID这一项则设置。否则设为INVALID_ID
long dataId = js.has(DataColumns.ID) ? js.getLong(DataColumns.ID) : INVALID_ID;
if (mIsCreate || mDataId != dataId) {
mDiffDataValues.put(DataColumns.ID, dataId);
@ -130,12 +152,16 @@ public class SqlData {
mDataContentData3 = dataContentData3;
}
/*
*/
public JSONObject getContent() throws JSONException {
if (mIsCreate) {
Log.e(TAG, "it seems that we haven't created this in database yet");
return null;
}
JSONObject js = new JSONObject();
//创建JSONObject对象并将相关数据放入其中并返回。
JSONObject js = new JSONObject();//构建JSONObject对象并将相关数据放入其中并返回。
js.put(DataColumns.ID, mDataId);
js.put(DataColumns.MIME_TYPE, mDataMimeType);
js.put(DataColumns.CONTENT, mDataContent);
@ -144,6 +170,9 @@ public class SqlData {
return js;
}
/*
commit
*/
public void commit(long noteId, boolean validateVersion, long version) {
if (mIsCreate) {
@ -182,7 +211,9 @@ public class SqlData {
mDiffDataValues.clear();
mIsCreate = false;
}
/*
id
*/
public long getId() {
return mDataId;
}

@ -37,12 +37,15 @@ import org.json.JSONObject;
import java.util.ArrayList;
/*
TAG
getSimpleName()
*/
public class SqlNote {
private static final String TAG = SqlNote.class.getSimpleName();
private static final int INVALID_ID = -99999;
//集合了interface NoteColumns中所有SF常量17个
public static final String[] PROJECTION_NOTE = new String[] {
NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID,
NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE,
@ -52,6 +55,7 @@ public class SqlNote {
NoteColumns.VERSION
};
//以下设置17个列的编号
public static final int ID_COLUMN = 0;
public static final int ALERTED_DATE_COLUMN = 1;
@ -86,6 +90,7 @@ public class SqlNote {
public static final int VERSION_COLUMN = 16;
//以下定义了17个内部的变量其中12个可以由content中获得5个需要初始化为0或者new
private Context mContext;
private ContentResolver mContentResolver;
@ -122,16 +127,20 @@ public class SqlNote {
private ArrayList<SqlData> mDataList;
/*
context
*/
public SqlNote(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = true;
mIsCreate = true;//mIsCreate用于标示构造方式
mId = INVALID_ID;
mAlertDate = 0;
mBgColorId = ResourceParser.getDefaultBgId(context);
mCreatedDate = System.currentTimeMillis();
mCreatedDate = System.currentTimeMillis();//调用系统函数获得创建时间
mHasAttachment = 0;
mModifiedDate = System.currentTimeMillis();
mModifiedDate = System.currentTimeMillis();//最后一次修改时间初始化为创建时间
mParentId = 0;
mSnippet = "";
mType = Notes.TYPE_NOTE;
@ -143,10 +152,14 @@ public class SqlNote {
mDataList = new ArrayList<SqlData>();
}
/*
contextcursor,cursor
*/
public SqlNote(Context context, Cursor c) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
mIsCreate = false;//mIsCreate用于标示构造方式
loadFromCursor(c);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
@ -154,10 +167,13 @@ public class SqlNote {
mDiffNoteValues = new ContentValues();
}
/*
*/
public SqlNote(Context context, long id) {
mContext = context;
mContentResolver = context.getContentResolver();
mIsCreate = false;
mIsCreate = false;//mIsCreate用于标示构造方式
loadFromCursor(id);
mDataList = new ArrayList<SqlData>();
if (mType == Notes.TYPE_NOTE)
@ -166,16 +182,20 @@ public class SqlNote {
}
/*
id
*/
private void loadFromCursor(long id) {
Cursor c = null;
try {
c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)",
new String[] {
String.valueOf(id)
}, null);
}, null);//通过id获得对应的ContentResolver中的cursor
if (c != null) {
c.moveToNext();
loadFromCursor(c);
loadFromCursor(c);//然后加载数据进行初始化
//SqlNote(Context context,long id)与SqlNote(Context context,long id)的实现方式基本相同
} else {
Log.w(TAG, "loadFromCursor: cursor = null");
}
@ -185,7 +205,11 @@ public class SqlNote {
}
}
/*
*/
private void loadFromCursor(Cursor c) {
//直接从一条记录中获得以下变量的初始值
mId = c.getLong(ID_COLUMN);
mAlertDate = c.getLong(ALERTED_DATE_COLUMN);
mBgColorId = c.getInt(BG_COLOR_ID_COLUMN);
@ -200,6 +224,9 @@ public class SqlNote {
mVersion = c.getLong(VERSION_COLUMN);
}
/*
content
*/
private void loadDataContent() {
Cursor c = null;
mDataList.clear();
@ -226,6 +253,9 @@ public class SqlNote {
}
}
/*
content
*/
public boolean setContent(JSONObject js) {
try {
JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE);
@ -359,6 +389,9 @@ public class SqlNote {
return true;
}
/*
contentnote
*/
public JSONObject getContent() {
try {
JSONObject js = new JSONObject();
@ -369,7 +402,7 @@ public class SqlNote {
}
JSONObject note = new JSONObject();
if (mType == Notes.TYPE_NOTE) {
if (mType == Notes.TYPE_NOTE) {//类型为note时
note.put(NoteColumns.ID, mId);
note.put(NoteColumns.ALERTED_DATE, mAlertDate);
note.put(NoteColumns.BG_COLOR_ID, mBgColorId);
@ -407,39 +440,66 @@ public class SqlNote {
return null;
}
/*
idid
*/
public void setParentId(long id) {
mParentId = id;
mDiffNoteValues.put(NoteColumns.PARENT_ID, id);
}
/*
idGtaskid
*/
public void setGtaskId(String gid) {
mDiffNoteValues.put(NoteColumns.GTASK_ID, gid);
}
/*
idid
*/
public void setSyncId(long syncId) {
mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId);
}
/*
*/
public void resetLocalModified() {
mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0);
}
/*
id
*/
public long getId() {
return mId;
}
/*
idid
*/
public long getParentId() {
return mParentId;
}
/*
便
*/
public String getSnippet() {
return mSnippet;
}
/*
便
*/
public boolean isNoteType() {
return mType == Notes.TYPE_NOTE;
}
/*
commit
*/
public void commit(boolean validateVersion) {
if (mIsCreate) {
if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) {
@ -458,7 +518,7 @@ public class SqlNote {
}
if (mType == Notes.TYPE_NOTE) {
for (SqlData sqlData : mDataList) {
for (SqlData sqlData : mDataList) {//直接使用sqldata中的实现
sqlData.commit(mId, false, -1);
}
}
@ -470,7 +530,7 @@ public class SqlNote {
if (mDiffNoteValues.size() > 0) {
mVersion ++;
int result = 0;
if (!validateVersion) {
if (!validateVersion) {//构造字符串
result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "("
+ NoteColumns.ID + "=?)", new String[] {
String.valueOf(mId)

@ -35,22 +35,22 @@ import org.json.JSONObject;
public class Task extends Node {
private static final String TAG = Task.class.getSimpleName();
private boolean mCompleted;
private boolean mCompleted;//是否完成
private String mNotes;
private JSONObject mMetaInfo;
private JSONObject mMetaInfo;// 将在示例中中存储数据的类型
private Task mPriorSibling;
private Task mPriorSibling;//对用的优先兄弟Task的指针待完善
private TaskList mParent;
private TaskList mParent;//所在的任务列表指针
public Task() {
super();
mCompleted = false;
mNotes = null;
mPriorSibling = null;
mParent = null;
mPriorSibling = null;//TaskList中当前Task前面的Task的指针
mParent = null;//当前Task所在的TaskList
mMetaInfo = null;
}

@ -31,11 +31,11 @@ import java.util.ArrayList;
public class TaskList extends Node {
private static final String TAG = TaskList.class.getSimpleName();
private static final String TAG = TaskList.class.getSimpleName();//tag标记
private int mIndex;
private int mIndex;//当前TaskList的指针
private ArrayList<Task> mChildren;
private ArrayList<Task> mChildren;//类中主要保存数据的单元用来实现一个以Task为元素的ArrayList
public TaskList() {
super();
@ -43,6 +43,9 @@ public class TaskList extends Node {
mIndex = 1;
}
/*
JSONObject
*/
public JSONObject getCreateAction(int actionId) {
JSONObject js = new JSONObject();
@ -58,7 +61,7 @@ public class TaskList extends Node {
js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex);
// entity_delta
JSONObject entity = new JSONObject();
JSONObject entity = new JSONObject();//entity实体
entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName());
entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null");
entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE,
@ -74,6 +77,9 @@ public class TaskList extends Node {
return js;
}
/*
JSONObject
*/
public JSONObject getUpdateAction(int actionId) {
JSONObject js = new JSONObject();
@ -229,11 +235,16 @@ public class TaskList extends Node {
task.setPriorSibling(mChildren.isEmpty() ? null : mChildren
.get(mChildren.size() - 1));
task.setParent(this);
//注意每一次ArrayList的变化都要紧跟相关Task中PriorSibling的更改
//接下来几个函数都有相关操作
}
}
return ret;
}
/*
*/
public boolean addChildTask(Task task, int index) {
if (index < 0 || index > mChildren.size()) {
Log.e(TAG, "add child task: invalid index");
@ -260,6 +271,9 @@ public class TaskList extends Node {
return true;
}
/*
TaskListtask
*/
public boolean removeChildTask(Task task) {
boolean ret = false;
int index = mChildren.indexOf(task);
@ -281,6 +295,9 @@ public class TaskList extends Node {
return ret;
}
/*
TaskListTaskindex
*/
public boolean moveChildTask(Task task, int index) {
if (index < 0 || index >= mChildren.size()) {
@ -297,8 +314,12 @@ public class TaskList extends Node {
if (pos == index)
return true;
return (removeChildTask(task) && addChildTask(task, index));
//利用已经实现好的功能完成当下功能
}
/*
gidTask
*/
public Task findChildTaskByGid(String gid) {
for (int i = 0; i < mChildren.size(); i++) {
Task t = mChildren.get(i);
@ -309,10 +330,16 @@ public class TaskList extends Node {
return null;
}
/*
Taskindex
*/
public int getChildTaskIndex(Task task) {
return mChildren.indexOf(task);
}
/*
indexTask
*/
public Task getChildTaskByIndex(int index) {
if (index < 0 || index >= mChildren.size()) {
Log.e(TAG, "getTaskByIndex: invalid index");
@ -321,8 +348,11 @@ public class TaskList extends Node {
return mChildren.get(index);
}
/*
gidTask
*/
public Task getChilTaskByGid(String gid) {
for (Task task : mChildren) {
for (Task task : mChildren) {//一种常见的ArrayList的遍历算法四种
if (task.getGid().equals(gid))
return task;
}

@ -18,11 +18,20 @@ package net.micode.notes.gtask.exception;
public class ActionFailureException extends RuntimeException {
private static final long serialVersionUID = 4425249765923293627L;
/*
serialVersionUIDjava
serialVersionUID
*/
public ActionFailureException() {
super();
}
/*
JAVA使superthis
new
使super
supersuper(paramString)Exception()Exception(paramString)
*/
public ActionFailureException(String paramString) {
super(paramString);
}

@ -18,10 +18,20 @@ package net.micode.notes.gtask.exception;
public class NetworkFailureException extends Exception {
private static final long serialVersionUID = 2107610287180234136L;
/*
serialVersionUIDjava
serialVersionUID
*/
public NetworkFailureException() {
super();
}
/*
JAVA使superthis.
new
使super
super()super (paramString)Exception ()Exception (paramString)
*/
public NetworkFailureException(String paramString) {
super(paramString);

@ -17,6 +17,14 @@
package net.micode.notes.gtask.remote;
/*
GTask
private void showNotification(int tickerId,String content)
protected Integer doInBackground(Void... unused) 线
protected void onProgressUpdate(String... progress) 使 线
protected void onPostExecute(Integer result) Handler UI使doInBackground UI
*/
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@ -28,6 +36,14 @@ import net.micode.notes.R;
import net.micode.notes.ui.NotesListActivity;
import net.micode.notes.ui.NotesPreferenceActivity;
/*
GTask
private void showNotification(int tickerId, String content)
protected Integer doInBackground(Void... unused) 线
protected void onProgressUpdate(String... progress) 使 线
protected void onPostExecute(Integer result) Handler UI使doInBackground UI
*/
public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
@ -57,7 +73,7 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
mTaskManager.cancelSync();
}
public void publishProgess(String message) {
public void publishProgess(String message) {//发现进度单位系统将会调用onProgressUpdate()方法更新这些值
publishProgress(new String[] {
message
});
@ -66,43 +82,43 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
private void showNotification(int tickerId, String content) {
Notification notification = new Notification(R.drawable.notification, mContext
.getString(tickerId), System.currentTimeMillis());
notification.defaults = Notification.DEFAULT_LIGHTS;
notification.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent pendingIntent;
notification.defaults = Notification.DEFAULT_LIGHTS;//调用系统自带灯光
notification.flags = Notification.FLAG_AUTO_CANCEL;//点击清除按钮或者点击通知后自觉消失
PendingIntent pendingIntent;//描述了想要启动一个Activity、Broadcast或者是Service的意图
if (tickerId != R.string.ticker_success) {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesPreferenceActivity.class), 0);
NotesPreferenceActivity.class), 0);//如果同步不成功那么从系统取得一个用于启动一个NotesPreferenceActivity的PendingIntent对象
} else {
pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
NotesListActivity.class), 0);
NotesListActivity.class), 0);//如果同步成功那么从系统取得一个用于启动NotesListActivity的PendingIntent对象
}
notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
pendingIntent);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);//通过NotificationManager对象的notify方法来执行一个notification的消息
}
@Override
protected Integer doInBackground(Void... unused) {
publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
.getSyncAccountName(mContext)));
return mTaskManager.sync(mContext, this);
.getSyncAccountName(mContext)));//利用getString,将把 NotesPreferenceActivity.getSyncAccountName(mContext))的字符串内容传进sync_progress_login中
return mTaskManager.sync(mContext, this);//进行后台同步具体操作
}
@Override
protected void onProgressUpdate(String... progress) {
showNotification(R.string.ticker_syncing, progress[0]);
if (mContext instanceof GTaskSyncService) {
if (mContext instanceof GTaskSyncService) {//instanceof 判断mContext是否是GTaskSyncService的实例
((GTaskSyncService) mContext).sendBroadcast(progress[0]);
}
}
@Override
protected void onPostExecute(Integer result) {
protected void onPostExecute(Integer result) {//用于执行完成后台任务后更新UI显示结果
if (result == GTaskManager.STATE_SUCCESS) {
showNotification(R.string.ticker_success, mContext.getString(
R.string.success_sync_account, mTaskManager.getSyncAccount()));
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());
NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());//设置最新更新时间
} else if (result == GTaskManager.STATE_NETWORK_ERROR) {
showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
} else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
@ -110,11 +126,12 @@ public class GTaskASyncTask extends AsyncTask<Void, String, Integer> {
} else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
showNotification(R.string.ticker_cancel, mContext
.getString(R.string.error_sync_cancelled));
}
}//几种不同情况下的显示结果
if (mOnCompleteListener != null) {
new Thread(new Runnable() {
new Thread(new Runnable() {//一个线程方法
public void run() {//完成后的操作使用onComplete()将所有值都重新初始化,相当于完成一次操作
public void run() {
mOnCompleteListener.onComplete();
}
}).start();

@ -59,12 +59,15 @@ import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
/*
GTASKGTASK
使accountManager JSONObject HttpParams authToken Gid
*/
public class GTaskClient {
private static final String TAG = GTaskClient.class.getSimpleName();
private static final String GTASK_URL = "https://mail.google.com/tasks/";
private static final String GTASK_URL = "https://mail.google.com/tasks/";//指定的URL
private static final String GTASK_GET_URL = "https://mail.google.com/tasks/ig";
@ -102,6 +105,11 @@ public class GTaskClient {
mUpdateArray = null;
}
/*
使 getInstance()
mInstance
*/
public static synchronized GTaskClient getInstance() {
if (mInstance == null) {
mInstance = new GTaskClient();
@ -109,42 +117,51 @@ public class GTaskClient {
return mInstance;
}
/*
Activity
使URL使URL
truefalse
*/
public boolean login(Activity activity) {
// we suppose that the cookie would expire after 5 minutes
// then we need to re-login
//判断距离最后一次登录操作是否超过5分钟
final long interval = 1000 * 60 * 5;
if (mLastLoginTime + interval < System.currentTimeMillis()) {
mLoggedin = false;
}
// need to re-login after account switch
//重新登录操作
if (mLoggedin
&& !TextUtils.equals(getSyncAccount().name, NotesPreferenceActivity
.getSyncAccountName(activity))) {
mLoggedin = false;
}
//如果没有超过时间,则不需要重新登录
if (mLoggedin) {
Log.d(TAG, "already logged in");
return true;
}
mLastLoginTime = System.currentTimeMillis();
String authToken = loginGoogleAccount(activity, false);
mLastLoginTime = System.currentTimeMillis();//更新最后登录时间,改为系统当前的时间
String authToken = loginGoogleAccount(activity, false);//判断是否登录到谷歌账户
if (authToken == null) {
Log.e(TAG, "login google account failed");
return false;
}
// login with custom domain if necessary
//尝试使用用户自己的域登录名
if (!(mAccount.name.toLowerCase().endsWith("gmail.com") || mAccount.name.toLowerCase()
.endsWith("googlemail.com"))) {
StringBuilder url = new StringBuilder(GTASK_URL).append("a/");
int index = mAccount.name.indexOf('@') + 1;
String suffix = mAccount.name.substring(index);
url.append(suffix + "/");
mGetUrl = url.toString() + "ig";
mPostUrl = url.toString() + "r/ig";
mGetUrl = url.toString() + "ig";//设置用户对应的getUrl
mPostUrl = url.toString() + "r/ig";//设置用户对应的postUrl
if (tryToLoginGtask(activity, authToken)) {
mLoggedin = true;
@ -152,6 +169,7 @@ public class GTaskClient {
}
// try to login with google official url
//如果账户无法登录则使用谷歌官方的URL进行登录
if (!mLoggedin) {
mGetUrl = GTASK_GET_URL;
mPostUrl = GTASK_POST_URL;
@ -164,10 +182,16 @@ public class GTaskClient {
return true;
}
/*
使
使AccountManager
*/
private String loginGoogleAccount(Activity activity, boolean invalidateToken) {
String authToken;
AccountManager accountManager = AccountManager.get(activity);
Account[] accounts = accountManager.getAccountsByType("com.google");
String authToken;//令牌,是登录操作保证安全性的唯一方法
AccountManager accountManager = AccountManager.get(activity);//AccountManager这个类给用户提供了集中注册账号的接口
Account[] accounts = accountManager.getAccountsByType("com.google");//获取全部以com.google结尾的account
if (accounts.length == 0) {
Log.e(TAG, "there is no available google account");
@ -176,6 +200,7 @@ public class GTaskClient {
String accountName = NotesPreferenceActivity.getSyncAccountName(activity);
Account account = null;
//遍历获得的accounts信息寻找已经记录过的账户信息
for (Account a : accounts) {
if (a.name.equals(accountName)) {
account = a;
@ -190,11 +215,13 @@ public class GTaskClient {
}
// get the token now
//获取选中账号的令牌
AccountManagerFuture<Bundle> accountManagerFuture = accountManager.getAuthToken(account,
"goanna_mobile", null, activity, null, null);
try {
Bundle authTokenBundle = accountManagerFuture.getResult();
authToken = authTokenBundle.getString(AccountManager.KEY_AUTHTOKEN);
//如果是invalidateToken那么需要调用invalidateAuthToken(String, String)方法废除这个无效token
if (invalidateToken) {
accountManager.invalidateAuthToken("com.google", authToken);
loginGoogleAccount(activity, false);
@ -207,10 +234,12 @@ public class GTaskClient {
return authToken;
}
//尝试登陆Gtask这只是一个预先判断令牌是否是有效以及是否能登上GTask的方法,而不是具体实现登陆的方法
private boolean tryToLoginGtask(Activity activity, String authToken) {
if (!loginGtask(authToken)) {
// maybe the auth token is out of date, now let's invalidate the
// token and try again
//删除过一个屋下的authToken,申请一个新的后再次尝试登录
authToken = loginGoogleAccount(activity, true);
if (authToken == null) {
Log.e(TAG, "login google account failed");
@ -225,25 +254,27 @@ public class GTaskClient {
return true;
}
//功能描述实现登录GTask的具体操作
private boolean loginGtask(String authToken) {
int timeoutConnection = 10000;
int timeoutSocket = 15000;
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
int timeoutSocket = 15000;//socket是一种通信连续实现数据的交换接口
HttpParams httpParameters = new BasicHttpParams();//实例化一个新的HTTP参数类
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);//设置连接超时情况
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);//设置设置端口超时时间
mHttpClient = new DefaultHttpClient(httpParameters);
BasicCookieStore localBasicCookieStore = new BasicCookieStore();
BasicCookieStore localBasicCookieStore = new BasicCookieStore();//设置本地cookie
mHttpClient.setCookieStore(localBasicCookieStore);
HttpProtocolParams.setUseExpectContinue(mHttpClient.getParams(), false);
// login gtask
try {
String loginUrl = mGetUrl + "?auth=" + authToken;
HttpGet httpGet = new HttpGet(loginUrl);
String loginUrl = mGetUrl + "?auth=" + authToken;//设置登录的url
HttpGet httpGet = new HttpGet(loginUrl);//通过登录的url实例化网页上资源的查找
HttpResponse response = null;
response = mHttpClient.execute(httpGet);
// get the cookie now
//获取CookieStore里存放的cookie,看如果存有“GTL(不知道什么意思)”则说明有验证成功的有效的cookie
List<Cookie> cookies = mHttpClient.getCookieStore().getCookies();
boolean hasAuthCookie = false;
for (Cookie cookie : cookies) {
@ -256,6 +287,7 @@ public class GTaskClient {
}
// get the client version
//获取client的内容具体操作是在返回的Content中截取从_setup(开始到)}</script>中间的字符串内容也就是gtask_url的内容
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}</script>";
@ -284,6 +316,11 @@ public class GTaskClient {
return mActionId++;
}
/*
使HttpPost
httpPost
*/
private HttpPost createHttpPost() {
HttpPost httpPost = new HttpPost(mPostUrl);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
@ -291,24 +328,30 @@ public class GTaskClient {
return httpPost;
}
/*
URL
使getContentEncoding()
*/
private String getResponseContent(HttpEntity entity) throws IOException {
String contentEncoding = null;
if (entity.getContentEncoding() != null) {
if (entity.getContentEncoding() != null) {//通过URL得到HttpEntity对象如果不为空则使用getContent方法创建一个流将数据从网络都过来
contentEncoding = entity.getContentEncoding().getValue();
Log.d(TAG, "encoding: " + contentEncoding);
}
InputStream input = entity.getContent();
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {
if (contentEncoding != null && contentEncoding.equalsIgnoreCase("gzip")) {//GZIP是使用DEFLATE进行压缩数据的另一个压缩库
input = new GZIPInputStream(entity.getContent());
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {
} else if (contentEncoding != null && contentEncoding.equalsIgnoreCase("deflate")) {//DEFLATE是一个无专利的压缩算法。他可以实现无损数据压缩
Inflater inflater = new Inflater(true);
input = new InflaterInputStream(entity.getContent(), inflater);
}
try {
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(isr);//是一个包装类,他可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了时候,再读入内存,是为了提供读的效率而设计的
StringBuilder sb = new StringBuilder();
while (true) {
@ -323,20 +366,29 @@ public class GTaskClient {
}
}
/*
JSON
jsonjs
UrlEncodedFormEntity entityhttpPost.setEntity(entity)jshttpPost
使getResponseContent
json
*/
private JSONObject postRequest(JSONObject js) throws NetworkFailureException {
if (!mLoggedin) {
if (!mLoggedin) {//未登录
Log.e(TAG, "please login first");
throw new ActionFailureException("not logged in");
}
//实例化一个httpPost的对象用来向服务器传输数据在这里就是发送请求而请求的内容在js里
HttpPost httpPost = createHttpPost();
try {
LinkedList<BasicNameValuePair> list = new LinkedList<BasicNameValuePair>();
list.add(new BasicNameValuePair("r", js.toString()));
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");//UrlEncodedFormEntity(),的形式比较单一,是普通的键值对
httpPost.setEntity(entity);
// execute the post
//执行这个请求
HttpResponse response = mHttpClient.execute(httpPost);
String jsString = getResponseContent(response.getEntity());
return new JSONObject(jsString);
@ -360,6 +412,13 @@ public class GTaskClient {
}
}
/*
.gtask.data.TaskTask
jsonTask,jsPost
postRequest
使task.setGidtasknew_ID
*/
public void createTask(Task task) throws NetworkFailureException {
commitUpdate();
try {
@ -386,6 +445,7 @@ public class GTaskClient {
}
}
//功能描述创建一个任务列表与createTask几乎一样区别就是最后设置的是tasklist的gid
public void createTaskList(TaskList tasklist) throws NetworkFailureException {
commitUpdate();
try {
@ -412,6 +472,11 @@ public class GTaskClient {
}
}
/*
使JSONObject使jsPost.putPutUpdateArrayClientVersion
使postRequestjspost,
*/
public void commitUpdate() throws NetworkFailureException {
if (mUpdateArray != null) {
try {
@ -433,6 +498,10 @@ public class GTaskClient {
}
}
/*
commitUpdate()
*/
public void addUpdateNode(Node node) throws NetworkFailureException {
if (node != null) {
// too many update items may result in an error
@ -447,6 +516,12 @@ public class GTaskClient {
}
}
/*
task,tasktask
getGidtaskgid
JSONObject.put(String name, Object value)task
postRequest
*/
public void moveTask(Task task, TaskList preParent, TaskList curParent)
throws NetworkFailureException {
commitUpdate();
@ -463,6 +538,7 @@ public class GTaskClient {
if (preParent == curParent && task.getPriorSibling() != null) {
// put prioring_sibing_id only if moving within the tasklist and
// it is not the first one
//设置优先级ID只有当移动时发生在文件中
action.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, task.getPriorSibling());
}
action.put(GTaskStringUtils.GTASK_JSON_SOURCE_LIST, preParent.getGid());
@ -472,6 +548,7 @@ public class GTaskClient {
action.put(GTaskStringUtils.GTASK_JSON_DEST_LIST, curParent.getGid());
}
actionList.put(action);
//最后将ACTION_LIST加到jsPost中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
@ -486,6 +563,11 @@ public class GTaskClient {
}
}
/*
JSON
使postRequest
*/
public void deleteNode(Node node) throws NetworkFailureException {
commitUpdate();
try {
@ -494,7 +576,7 @@ public class GTaskClient {
// action_list
node.setDeleted(true);
actionList.put(node.getUpdateAction(getActionId()));
actionList.put(node.getUpdateAction(getActionId()));//这里会获取到删除操作的ID加入到actionLiast中
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
// client_version
@ -509,6 +591,11 @@ public class GTaskClient {
}
}
/*
GetURI使getResponseContent
"_setup(")}</script>GTASK_JSON_LISTS
*/
public JSONArray getTaskLists() throws NetworkFailureException {
if (!mLoggedin) {
Log.e(TAG, "please login first");
@ -521,6 +608,7 @@ public class GTaskClient {
response = mHttpClient.execute(httpGet);
// get the task list
//筛选工作把筛选出的字符串放入jsString
String resString = getResponseContent(response.getEntity());
String jsBegin = "_setup(";
String jsEnd = ")}</script>";
@ -531,6 +619,7 @@ public class GTaskClient {
jsString = resString.substring(begin + jsBegin.length(), end);
}
JSONObject js = new JSONObject(jsString);
//获取GTASK_JSON_LISTS
return js.getJSONObject("t").getJSONArray(GTaskStringUtils.GTASK_JSON_LISTS);
} catch (ClientProtocolException e) {
Log.e(TAG, e.toString());
@ -547,6 +636,9 @@ public class GTaskClient {
}
}
/*
TASKListgid,
*/
public JSONArray getTaskList(String listGid) throws NetworkFailureException {
commitUpdate();
try {
@ -558,7 +650,7 @@ public class GTaskClient {
action.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE,
GTaskStringUtils.GTASK_JSON_ACTION_TYPE_GETALL);
action.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, getActionId());
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);
action.put(GTaskStringUtils.GTASK_JSON_LIST_ID, listGid);//设置传入的listGid
action.put(GTaskStringUtils.GTASK_JSON_GET_DELETED, false);
actionList.put(action);
jsPost.put(GTaskStringUtils.GTASK_JSON_ACTION_LIST, actionList);
@ -579,6 +671,7 @@ public class GTaskClient {
return mAccount;
}
//功能描述:重置更新的内容
public void resetUpdateArray() {
mUpdateArray = null;
}

@ -87,33 +87,44 @@ public class GTaskManager {
private HashMap<Long, String> mNidToGid;
private GTaskManager() {
mSyncing = false;
mCancelled = false;
mGTaskListHashMap = new HashMap<String, TaskList>();
private GTaskManager() {//设置初始化函数
mSyncing = false;//正在同步flase代表未执行
mCancelled = false;//全局标识flase代表可以执行
mGTaskListHashMap = new HashMap<String, TaskList>();//<>代表Java的泛型,就是创建一个用类型作为参数的类。
mGTaskHashMap = new HashMap<String, Node>();
mMetaHashMap = new HashMap<String, MetaData>();
mMetaList = null;
mLocalDeleteIdMap = new HashSet<Long>();
mGidToNid = new HashMap<String, Long>();
mNidToGid = new HashMap<Long, String>();
mNidToGid = new HashMap<Long, String>();//NodeID to GoogleID???通过hashmap散列表建立映射
}
public static synchronized GTaskManager getInstance() {
/*
synchronized线
*/
public static synchronized GTaskManager getInstance() {//可能运行在多线程环境下,使用语言级同步--synchronized
if (mInstance == null) {
mInstance = new GTaskManager();
}
return mInstance;
}
/*
synchronized线
*/
public synchronized void setActivityContext(Activity activity) {
// used for getting authtoken
mActivity = activity;
}
public int sync(Context context, GTaskASyncTask asyncTask) {
/*
context-----
param asyncTask-------
*/
public int sync(Context context, GTaskASyncTask asyncTask) {//核心函数
if (mSyncing) {
Log.d(TAG, "Sync is in progress");
Log.d(TAG, "Sync is in progress");//创建日志文件调试信息debug
return STATE_SYNC_IN_PROGRESS;
}
mContext = context;
@ -128,8 +139,8 @@ public class GTaskManager {
mNidToGid.clear();
try {
GTaskClient client = GTaskClient.getInstance();
client.resetUpdateArray();
GTaskClient client = GTaskClient.getInstance();//getInstance即为创建一个实例,client--客户机
client.resetUpdateArray();//JSONArray类型reset即置为NULL
// login google task
if (!mCancelled) {
@ -140,15 +151,15 @@ public class GTaskManager {
// get the task list from google
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list));
initGTaskList();
initGTaskList();//获取Google上的JSONtasklist转为本地TaskList
// do content sync work
asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing));
syncContent();
} catch (NetworkFailureException e) {
Log.e(TAG, e.toString());
} catch (NetworkFailureException e) {//分为两种异常,此类异常为网络异常
Log.e(TAG, e.toString());//创建日志文件调试信息。error
return STATE_NETWORK_ERROR;
} catch (ActionFailureException e) {
} catch (ActionFailureException e) {//此类异常为操作异常
Log.e(TAG, e.toString());
return STATE_INTERNAL_ERROR;
} catch (Exception e) {
@ -168,30 +179,39 @@ public class GTaskManager {
return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS;
}
/*
GtaskListGoogleJSONtasklistTaskList
mMetaListmGTaskListHashMapmGTaskHashMap
*/
private void initGTaskList() throws NetworkFailureException {
if (mCancelled)
return;
GTaskClient client = GTaskClient.getInstance();
GTaskClient client = GTaskClient.getInstance();//
try {
/*
JsonName Value()MapJsonObjectbantouyan-jsonJsonJson
{"key1":value1,"key2",value2....};key
ajaxjsjson使
*/
JSONArray jsTaskLists = client.getTaskLists();
// init meta list first
mMetaList = null;
mMetaList = null;//TaskList类型
for (int i = 0; i < jsTaskLists.length(); i++) {
JSONObject object = jsTaskLists.getJSONObject(i);
JSONObject object = jsTaskLists.getJSONObject(i);//JSONObject与JSONArray一个为对象一个为数组。此处取出单个JASONObject
String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID);
String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME);
if (name
.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) {
mMetaList = new TaskList();
mMetaList.setContentByRemoteJSON(object);
mMetaList = new TaskList();//MetaList意为元表,Tasklist类型此处为初始化
mMetaList.setContentByRemoteJSON(object);//将JSON中部分数据复制到自己定义的对象中相对应的数据name->mname...
// load meta data
JSONArray jsMetas = client.getTaskList(gid);
for (int j = 0; j < jsMetas.length(); j++) {
object = (JSONObject) jsMetas.getJSONObject(j);
MetaData metaData = new MetaData();
MetaData metaData = new MetaData();//继承自Node
metaData.setContentByRemoteJSON(object);
if (metaData.isWorthSaving()) {
mMetaList.addChildTask(metaData);
@ -247,13 +267,16 @@ public class GTaskManager {
}
}
/*
*/
private void syncContent() throws NetworkFailureException {
int syncType;
Cursor c = null;
Cursor c = null; //数据库指针
String gid;
Node node;
Node node;//Node包含Sync_Action的不同类型
mLocalDeleteIdMap.clear();
mLocalDeleteIdMap.clear();//HasnSet<Long>类型
if (mCancelled) {
return;
@ -301,8 +324,8 @@ public class GTaskManager {
node = mGTaskHashMap.get(gid);
if (node != null) {
mGTaskHashMap.remove(gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);
mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN));//通过hashmap建立联系
mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid);//通过hashmap建立联系
syncType = node.getSyncAction(c);
} else {
if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) {
@ -327,7 +350,7 @@ public class GTaskManager {
}
// go through remaining items
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();
Iterator<Map.Entry<String, Node>> iter = mGTaskHashMap.entrySet().iterator();//Tterator迭代器
while (iter.hasNext()) {
Map.Entry<String, Node> entry = iter.next();
node = entry.getValue();
@ -476,6 +499,9 @@ public class GTaskManager {
GTaskClient.getInstance().commitUpdate();
}
/*
syncTypeaddLocalNodeaddRemoteNodedeleteNodeupdateLocalNodeupdateRemoteNode
*/
private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
@ -522,6 +548,9 @@ public class GTaskManager {
}
}
/*
Node
*/
private void addLocalNode(Node node) throws NetworkFailureException {
if (mCancelled) {
return;
@ -596,6 +625,9 @@ public class GTaskManager {
updateRemoteMeta(node.getGid(), sqlNote);
}
/*
updatenode
*/
private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
@ -619,12 +651,16 @@ public class GTaskManager {
updateRemoteMeta(node.getGid(), sqlNote);
}
/*
Node
updateRemoteMeta
*/
private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
}
SqlNote sqlNote = new SqlNote(mContext, c);
SqlNote sqlNote = new SqlNote(mContext, c);//从本地mContext中获取内容
Node n;
// update remotely
@ -634,11 +670,13 @@ public class GTaskManager {
String parentGid = mNidToGid.get(sqlNote.getParentId());
if (parentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist");//调试信息
Log.e(TAG, "cannot find task's parent tasklist");
throw new ActionFailureException("cannot add remote task");
throw new ActionFailureException("cannot add remote task");//在本地生成的GTaskList中增加子结点
}
mGTaskListHashMap.get(parentGid).addChildTask(task);
//登录远程服务器创建Task
GTaskClient.getInstance().createTask(task);
n = (Node) task;
@ -656,6 +694,7 @@ public class GTaskManager {
else
folderName += sqlNote.getSnippet();
//iterator迭代器通过统一的接口迭代所有的map元素
Iterator<Map.Entry<String, TaskList>> iter = mGTaskListHashMap.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String, TaskList> entry = iter.next();
@ -692,6 +731,9 @@ public class GTaskManager {
mNidToGid.put(sqlNote.getId(), n.getGid());
}
/*
Nodemeta(updateRemoteMeta)
*/
private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException {
if (mCancelled) {
return;
@ -710,13 +752,16 @@ public class GTaskManager {
if (sqlNote.isNoteType()) {
Task task = (Task) node;
TaskList preParentList = task.getParent();
//preParentList为通过node获取的父节点列表
String curParentGid = mNidToGid.get(sqlNote.getParentId());
//curParentGid为通过光标在数据库中找到sqlNote的mParentId再通过mNidToGid由long类型转为String类型的Gid
if (curParentGid == null) {
Log.e(TAG, "cannot find task's parent tasklist");
throw new ActionFailureException("cannot update remote task");
}
TaskList curParentList = mGTaskListHashMap.get(curParentGid);
//通过HashMap找到对应Gid的TaskList
if (preParentList != curParentList) {
preParentList.removeChildTask(task);
@ -727,9 +772,14 @@ public class GTaskManager {
// clear local modified flag
sqlNote.resetLocalModified();
//commit到本地数据库
sqlNote.commit(true);
}
/*
meta meta----------
使SqlNote
*/
private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException {
if (sqlNote != null && sqlNote.isNoteType()) {
MetaData metaData = mMetaHashMap.get(gid);
@ -746,6 +796,9 @@ public class GTaskManager {
}
}
/*
syncID
*/
private void refreshLocalSyncId() throws NetworkFailureException {
if (mCancelled) {
return;
@ -790,10 +843,16 @@ public class GTaskManager {
}
}
/*
,mAccount.name
*/
public String getSyncAccount() {
return GTaskClient.getInstance().getSyncAccount().name;
}
/*
mCancelledtrue
*/
public void cancelSync() {
mCancelled = true;
}

@ -23,6 +23,22 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
/*
* Service
*
* private void startSync()
* private void cancelSync()
* public void onCreate()
* public int onStartCommand(Intent intent, int flags, int startId) serviceserviceservice
* public void onLowMemory() serviceservice
* public IBinder onBind()
* public void sendBroadcast(String msg)
* public static void startSync(Activity activity)
* public static void cancelSync(Context context)
* public static boolean isSyncing()
* public static String getProgressString()
*/
public class GTaskSyncService extends Service {
public final static String ACTION_STRING_NAME = "sync_action_type";
@ -42,6 +58,9 @@ public class GTaskSyncService extends Service {
private static String mSyncProgress = "";
/*
*/
private void startSync() {
if (mSyncTask == null) {
mSyncTask = new GTaskASyncTask(this, new GTaskASyncTask.OnCompleteListener() {
@ -52,7 +71,8 @@ public class GTaskSyncService extends Service {
}
});
sendBroadcast("");
mSyncTask.execute();
mSyncTask.execute();//这个函数让任务是以单线程队列方式或线程池队列方式运行
}
}
@ -63,7 +83,7 @@ public class GTaskSyncService extends Service {
}
@Override
public void onCreate() {
public void onCreate() {//初始化一个service
mSyncTask = null;
}
@ -72,6 +92,7 @@ public class GTaskSyncService extends Service {
Bundle bundle = intent.getExtras();
if (bundle != null && bundle.containsKey(ACTION_STRING_NAME)) {
switch (bundle.getInt(ACTION_STRING_NAME, ACTION_INVALID)) {
//两种情况,开始同步或者取消同步
case ACTION_START_SYNC:
startSync();
break;
@ -81,7 +102,7 @@ public class GTaskSyncService extends Service {
default:
break;
}
return START_STICKY;
return START_STICKY;//等待新的intent来是这个service继续运行
}
return super.onStartCommand(intent, flags, startId);
}
@ -99,20 +120,20 @@ public class GTaskSyncService extends Service {
public void sendBroadcast(String msg) {
mSyncProgress = msg;
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);
intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null);
Intent intent = new Intent(GTASK_SERVICE_BROADCAST_NAME);//创建一个新的Intent
intent.putExtra(GTASK_SERVICE_BROADCAST_IS_SYNCING, mSyncTask != null);//附加INTENT中的相应参数的值
intent.putExtra(GTASK_SERVICE_BROADCAST_PROGRESS_MSG, msg);
sendBroadcast(intent);
sendBroadcast(intent); //发送这个通知
}
public static void startSync(Activity activity) {
public static void startSync(Activity activity) {//执行一个serviceservice的内容里的同步动作就是开始同步
GTaskManager.getInstance().setActivityContext(activity);
Intent intent = new Intent(activity, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_START_SYNC);
activity.startService(intent);
}
public static void cancelSync(Context context) {
public static void cancelSync(Context context) {//执行一个serviceservice的内容里的同步动作就是取消同步
Intent intent = new Intent(context, GTaskSyncService.class);
intent.putExtra(GTaskSyncService.ACTION_STRING_NAME, GTaskSyncService.ACTION_CANCEL_SYNC);
context.startService(intent);

@ -15,15 +15,16 @@
*/
package net.micode.notes.model;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
import android.content.ContentProviderOperation;//批量的更新、插入、删除数据。
import android.content.ContentProviderResult;//操作的结果
import android.content.ContentUris;//用于添加和获取Uri后面的ID
import android.content.ContentValues;//一种用来存储基本数据类型数据的存储机制
import android.content.Context;//需要用该类来弄清楚调用者的实例
import android.content.OperationApplicationException;//操作应用程序容错
import android.net.Uri;//表示待操作的数据
import android.os.RemoteException;//远程容错
import android.util.Log;//输出日志,比如说出错、警告等
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
@ -49,8 +50,10 @@ public class Note {
values.put(NoteColumns.MODIFIED_DATE, createdTime);
values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.PARENT_ID, folderId);
values.put(NoteColumns.PARENT_ID, folderId);//将数据写入数据库表格
Uri uri = context.getContentResolver().insert(Notes.CONTENT_NOTE_URI, values);
//ContentResolver()主要是实现外部应用对ContentProvider中的数据
//进行添加、删除、修改和查询操作
long noteId = 0;
try {
@ -65,37 +68,61 @@ public class Note {
return noteId;
}
/*
*/
public Note() {
mNoteDiffValues = new ContentValues();
mNoteData = new NoteData();
}
/*
*/
public void setNoteValue(String key, String value) {
mNoteDiffValues.put(key, value);
mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1);
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
/*
//设置数据库表格的标签文本内容的数据
*/
public void setTextData(String key, String value) {
mNoteData.setTextData(key, value);
}
/*
ID
*/
public void setTextDataId(long id) {
mNoteData.setTextDataId(id);
}
/*
ID
*/
public long getTextDataId() {
return mNoteData.mTextDataId;
}
/*
:ID
*/
public void setCallDataId(long id) {
mNoteData.setCallDataId(id);
}
/*
:ID
*/
public void setCallData(String key, String value) {
mNoteData.setCallData(key, value);
}
/*
*/
public boolean isLocalModified() {
return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified();
}
@ -114,6 +141,7 @@ public class Note {
* {@link NoteColumns#MODIFIED_DATE}. For data safety, though update note fails, we also update the
* note data info
*/
//判断是否同步
if (context.getContentResolver().update(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), mNoteDiffValues, null,
null) == 0) {
@ -130,14 +158,17 @@ public class Note {
return true;
}
/*
便
*/
private class NoteData {
private long mTextDataId;
private ContentValues mTextDataValues;
private ContentValues mTextDataValues;//文本数据
private long mCallDataId;
private ContentValues mCallDataValues;
private ContentValues mCallDataValues;//电话号码数据
private static final String TAG = "NoteData";
@ -148,6 +179,7 @@ public class Note {
mCallDataId = 0;
}
//下面上述几个函数的具体表现
boolean isLocalModified() {
return mTextDataValues.size() > 0 || mCallDataValues.size() > 0;
}
@ -178,16 +210,18 @@ public class Note {
mNoteDiffValues.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
}
//下面函数的作用是将新的数据通过Uri的操作存储到数据库
Uri pushIntoContentResolver(Context context, long noteId) {
/**
* Check for safety
*/
//判断数据是否合法
if (noteId <= 0) {
throw new IllegalArgumentException("Wrong note id:" + noteId);
}
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = null;
ContentProviderOperation.Builder builder = null;//数据的操作列表
if(mTextDataValues.size() > 0) {
mTextDataValues.put(DataColumns.NOTE_ID, noteId);
@ -209,7 +243,7 @@ public class Note {
operationList.add(builder.build());
}
mTextDataValues.clear();
}
}//把文本数据存入DataColumns
if(mCallDataValues.size() > 0) {
mCallDataValues.put(DataColumns.NOTE_ID, noteId);
@ -231,7 +265,7 @@ public class Note {
operationList.add(builder.build());
}
mCallDataValues.clear();
}
}//把电话号码数据存入DataColumns
if (operationList.size() > 0) {
try {
@ -248,6 +282,6 @@ public class Note {
}
}
return null;
}
}//存储过程中的异常处理
}
}

@ -56,12 +56,14 @@ public class WorkingNote {
private Context mContext;
//声明DATA_PROJECTION字符串数组
private static final String TAG = "WorkingNote";
private boolean mIsDeleted;
private NoteSettingChangedListener mNoteSettingStatusListener;
//声明 NOTE_PROJECTION字符串数组
public static final String[] DATA_PROJECTION = new String[] {
DataColumns.ID,
DataColumns.CONTENT,
@ -115,6 +117,7 @@ public class WorkingNote {
}
// Existing note construct
//WorkingNote的构造函数
private WorkingNote(Context context, long noteId, long folderId) {
mContext = context;
mNoteId = noteId;
@ -124,11 +127,13 @@ public class WorkingNote {
loadNote();
}
// 加载Note
// 通过数据库调用query函数找到第一个条目
private void loadNote() {
Cursor cursor = mContext.getContentResolver().query(
ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, mNoteId), NOTE_PROJECTION, null,
null, null);
//若存在,储存相应信息
if (cursor != null) {
if (cursor.moveToFirst()) {
mFolderId = cursor.getLong(NOTE_PARENT_ID_COLUMN);
@ -139,13 +144,14 @@ public class WorkingNote {
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
}
cursor.close();
} else {
} else {//若不存在,报错
Log.e(TAG, "No note with id:" + mNoteId);
throw new IllegalArgumentException("Unable to find note with id " + mNoteId);
}
loadNoteData();
}
//加载NoteData
private void loadNoteData() {
Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] {
@ -153,7 +159,8 @@ public class WorkingNote {
}, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
//查到信息不为空
if (cursor.moveToFirst()) {//查看第一项是否存在
do {
String type = cursor.getString(DATA_MIME_TYPE_COLUMN);
if (DataConstants.NOTE.equals(type)) {
@ -165,7 +172,7 @@ public class WorkingNote {
} else {
Log.d(TAG, "Wrong note type with type:" + type);
}
} while (cursor.moveToNext());
} while (cursor.moveToNext());//查阅所有项,直到为空
}
cursor.close();
} else {
@ -174,9 +181,12 @@ public class WorkingNote {
}
}
// 创建空的Note
// 传参context文件夹idwidget背景颜色
public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) {
WorkingNote note = new WorkingNote(context, folderId);
//设定相关属性
note.setBgColorId(defaultBgColorId);
note.setWidgetId(widgetId);
note.setWidgetType(widgetType);
@ -187,9 +197,10 @@ public class WorkingNote {
return new WorkingNote(context, id, 0);
}
//保存Note
public synchronized boolean saveNote() {
if (isWorthSaving()) {
if (!existInDatabase()) {
if (isWorthSaving()) {//是否值得保存
if (!existInDatabase()) {//是否存在数据库中
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false;
@ -212,11 +223,14 @@ public class WorkingNote {
}
}
//是否在数据库中存在
public boolean existInDatabase() {
return mNoteId > 0;
}
//是否值得保存
private boolean isWorthSaving() {
// 被删除,或(不在数据库中 内容为空),或 本地已保存过
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent))
|| (existInDatabase() && !mNote.isLocalModified())) {
return false;
@ -225,10 +239,13 @@ public class WorkingNote {
}
}
// 设置mNoteSettingStatusListener
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
mNoteSettingStatusListener = l;
}
// 设置AlertDate
// 若 mAlertDate与data不同则更改mAlertDate并设定NoteValue
public void setAlertDate(long date, boolean set) {
if (date != mAlertDate) {
mAlertDate = date;
@ -239,15 +256,21 @@ public class WorkingNote {
}
}
//设定删除标记
public void markDeleted(boolean mark) {
//设定标记
mIsDeleted = mark;
if (mWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID
&& mWidgetType != Notes.TYPE_WIDGET_INVALIDE && mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onWidgetChanged();
// 调用mNoteSettingStatusListener的 onWidgetChanged方法
}
}
//设定背景颜色
public void setBgColorId(int id) {
//设定条件 id != mBgColorId
if (id != mBgColorId) {
mBgColorId = id;
if (mNoteSettingStatusListener != null) {
@ -257,7 +280,10 @@ public class WorkingNote {
}
}
// 设定检查列表模式
// 参数mode
public void setCheckListMode(int mode) {
//设定条件 mMode != mode
if (mMode != mode) {
if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode);
@ -267,81 +293,107 @@ public class WorkingNote {
}
}
// 设定WidgetType
// 参数type
public void setWidgetType(int type) {
if (type != mWidgetType) {
if (type != mWidgetType) {//设定条件 type != mWidgetType
mWidgetType = type;
// 调用Note的setNoteValue方法更改WidgetType
mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType));
}
}
// 设定WidgetId
// 参数id
public void setWidgetId(int id) {
if (id != mWidgetId) {
if (id != mWidgetId) {//设定条件 id != mWidgetId
mWidgetId = id;
mNote.setNoteValue(NoteColumns.WIDGET_ID, String.valueOf(mWidgetId));
// 调用Note的setNoteValue方法更改WidgetId
}
}
// 设定WorkingTex
// 参数更改的text
public void setWorkingText(String text) {
if (!TextUtils.equals(mContent, text)) {
if (!TextUtils.equals(mContent, text)) {//设定条件 mContent, text内容不同
mContent = text;
mNote.setTextData(DataColumns.CONTENT, mContent);
// 调用Note的setTextData方法更改WorkingText
}
}
// 转变mNote的CallData及CallNote信息
// 参数String phoneNumber, long callDate
public void convertToCallNote(String phoneNumber, long callDate) {
mNote.setCallData(CallNote.CALL_DATE, String.valueOf(callDate));
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER));
}
// 判断是否有时钟题型
public boolean hasClockAlert() {
return (mAlertDate > 0 ? true : false);
}
// 获取Content
public String getContent() {
return mContent;
}
// 获取AlertDate
public long getAlertDate() {
return mAlertDate;
}
// 获取ModifiedDate
public long getModifiedDate() {
return mModifiedDate;
}
// 获取背景颜色来源id
public int getBgColorResId() {
return NoteBgResources.getNoteBgResource(mBgColorId);
}
// 获取背景颜色id
public int getBgColorId() {
return mBgColorId;
}
// 获取标题背景颜色id
public int getTitleBgResId() {
return NoteBgResources.getNoteTitleBgResource(mBgColorId);
}
// 获取CheckListMode
public int getCheckListMode() {
return mMode;
}
// 获取便签id
public long getNoteId() {
return mNoteId;
}
// 获取文件夹id
public long getFolderId() {
return mFolderId;
}
// 获取WidgetId
public int getWidgetId() {
return mWidgetId;
}
// 获取WidgetType
public int getWidgetType() {
return mWidgetType;
}
// 创建接口 NoteSettingChangedListener,便签更新监视
// 为NoteEditActivity提供接口
// 提供函数有
public interface NoteSettingChangedListener {
/**
* Called when the background color of current note has just changed

@ -41,8 +41,13 @@ public class BackupUtils {
// Singleton stuff
private static BackupUtils sInstance;
/*
ynchronized ,线线A
,线BC D()使synchronized线BC D线A,,,
synchronized synchronized
*/
public static synchronized BackupUtils getInstance(Context context) {
if (sInstance == null) {
if (sInstance == null) {//如果当前备份不存在,则新声明一个
sInstance = new BackupUtils(context);
}
return sInstance;
@ -65,11 +70,12 @@ public class BackupUtils {
private TextExport mTextExport;
//初始化函数
private BackupUtils(Context context) {
mTextExport = new TextExport(context);
}
private static boolean externalStorageAvailable() {
private static boolean externalStorageAvailable() {//外部存储功能是否可用
return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
}
@ -132,6 +138,7 @@ public class BackupUtils {
mFileDirectory = "";
}
//获取文本的组成部分
private String getFormat(int id) {
return TEXT_FORMAT[id];
}
@ -140,7 +147,7 @@ public class BackupUtils {
* Export the folder identified by folder id to text
*/
private void exportFolderToText(String folderId, PrintStream ps) {
// Query notes belong to this folder
// Query notes belong to this folder 通过查询parent id是文件夹id的note来选出制定ID文件夹下的Note
Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] {
folderId
@ -149,13 +156,13 @@ public class BackupUtils {
if (notesCursor != null) {
if (notesCursor.moveToFirst()) {
do {
// Print note's last modified date
// Print note's last modified date ps里面保存有这份note的日期
ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format(
mContext.getString(R.string.format_datetime_mdhm),
notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE))));
// Query data belong to this note
String noteId = notesCursor.getString(NOTE_COLUMN_ID);
exportNoteToText(noteId, ps);
exportNoteToText(noteId, ps);//将文件导出到text
} while (notesCursor.moveToNext());
}
notesCursor.close();
@ -171,7 +178,7 @@ public class BackupUtils {
noteId
}, null);
if (dataCursor != null) {
if (dataCursor != null) {//利用光标来扫描内容区别为callnote和note两种靠ps.printline输出
if (dataCursor.moveToFirst()) {
do {
String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE);
@ -181,7 +188,7 @@ public class BackupUtils {
long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE);
String location = dataCursor.getString(DATA_COLUMN_CONTENT);
if (!TextUtils.isEmpty(phoneNumber)) {
if (!TextUtils.isEmpty(phoneNumber)) {//判断是否为空字符
ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT),
phoneNumber));
}
@ -218,7 +225,7 @@ public class BackupUtils {
/**
* Note will be exported as text which is user readable
*/
public int exportToText() {
public int exportToText() {//总函数调用上面的exportFolder和exportNote
if (!externalStorageAvailable()) {
Log.d(TAG, "Media was not mounted");
return STATE_SD_CARD_UNMOUONTED;
@ -229,7 +236,7 @@ public class BackupUtils {
Log.e(TAG, "get print stream error");
return STATE_SYSTEM_ERROR;
}
// First export folder and its notes
// First export folder and its notes 导出文件夹,就是导出里面包含的便签
Cursor folderCursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION,
@ -257,7 +264,7 @@ public class BackupUtils {
folderCursor.close();
}
// Export notes in root's folder
// Export notes in root's folder 将根目录里的便签导出(由于不属于任何文件夹,因此无法通过文件夹导出来实现这一部分便签的导出)
Cursor noteCursor = mContext.getContentResolver().query(
Notes.CONTENT_NOTE_URI,
NOTE_PROJECTION,
@ -298,6 +305,7 @@ public class BackupUtils {
try {
FileOutputStream fos = new FileOutputStream(file);
ps = new PrintStream(fos);
//将ps输出流输出到特定的文件目的就是导出到文件而不是直接输出
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
@ -314,16 +322,16 @@ public class BackupUtils {
*/
private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) {
StringBuilder sb = new StringBuilder();
sb.append(Environment.getExternalStorageDirectory());
sb.append(context.getString(filePathResId));
File filedir = new File(sb.toString());
sb.append(Environment.getExternalStorageDirectory());//外部SD卡的存储路径
sb.append(context.getString(filePathResId));//文件的存储路径
File filedir = new File(sb.toString());//filedir应该就是用来存储路径信息
sb.append(context.getString(
fileNameFormatResId,
DateFormat.format(context.getString(R.string.format_date_ymd),
System.currentTimeMillis())));
File file = new File(sb.toString());
try {
try {//如果这些文件不存在,则新建
if (!filedir.exists()) {
filedir.mkdir();
}
@ -336,7 +344,7 @@ public class BackupUtils {
} catch (IOException e) {
e.printStackTrace();
}
// try catch 异常处理
return null;
}
}

@ -52,13 +52,14 @@ public class DataUtils {
if(id == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Don't delete system folder root");
continue;
}
}//如果发现是根文件夹,则不删除
ContentProviderOperation.Builder builder = ContentProviderOperation
.newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id));
operationList.add(builder.build());
}
try {
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);
//数据库事务,数据库事务是由一组数据库操作序列组成,事务作为一个整体被执行
if (results == null || results.length == 0 || results[0] == null) {
Log.d(TAG, "delete notes failed, ids:" + ids.toString());
return false;
@ -94,7 +95,7 @@ public class DataUtils {
builder.withValue(NoteColumns.PARENT_ID, folderId);
builder.withValue(NoteColumns.LOCAL_MODIFIED, 1);
operationList.add(builder.build());
}
}//将ids里包含的每一列的数据逐次加入到operationList中等待最后的批量处理
try {
ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operationList);
@ -119,7 +120,7 @@ public class DataUtils {
new String[] { "COUNT(*)" },
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?",
new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)},
null);
null); //筛选条件源文件不为trash folder
int count = 0;
if(cursor != null) {
@ -141,11 +142,11 @@ public class DataUtils {
null,
NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER,
new String [] {String.valueOf(type)},
null);
null);//查询条件type符合且不属于垃圾文件夹
boolean exist = false;
if (cursor != null) {
if (cursor.getCount() > 0) {
if (cursor.getCount() > 0) {//用getcount函数判断cursor是否为空
exist = true;
}
cursor.close();
@ -187,6 +188,7 @@ public class DataUtils {
" AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER +
" AND " + NoteColumns.SNIPPET + "=?",
new String[] { name }, null);
//通过名字查询文件是否存在
boolean exist = false;
if(cursor != null) {
if(cursor.getCount() > 0) {
@ -202,7 +204,7 @@ public class DataUtils {
new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE },
NoteColumns.PARENT_ID + "=?",
new String[] { String.valueOf(folderId) },
null);
null);//查询条件父ID是传入的folderId;
HashSet<AppWidgetAttribute> set = null;
if (c != null) {
@ -211,13 +213,13 @@ public class DataUtils {
do {
try {
AppWidgetAttribute widget = new AppWidgetAttribute();
widget.widgetId = c.getInt(0);
widget.widgetType = c.getInt(1);
widget.widgetId = c.getInt(0);//0对应的NoteColumns.WIDGET_ID
widget.widgetType = c.getInt(1);//1对应的NoteColumns.WIDGET_TYPE
set.add(widget);
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, e.toString());
}
} while (c.moveToNext());
} while (c.moveToNext());//查询下一条
}
c.close();
}
@ -250,7 +252,7 @@ public class DataUtils {
+ CallNote.PHONE_NUMBER + ",?)",
new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber },
null);
//通过数据库操作查询条件是callDate和phoneNumber匹配传入参数的值
if (cursor != null) {
if (cursor.moveToFirst()) {
try {
@ -269,7 +271,7 @@ public class DataUtils {
new String [] { NoteColumns.SNIPPET },
NoteColumns.ID + "=?",
new String [] { String.valueOf(noteId)},
null);
null);//查询条件noteId
if (cursor != null) {
String snippet = "";
@ -282,6 +284,7 @@ public class DataUtils {
throw new IllegalArgumentException("Note is not found with id: " + noteId);
}
//对字符串进行格式处理,将字符串两头的空格去掉,同时将换行符去掉
public static String getFormattedSnippet(String snippet) {
if (snippet != null) {
snippet = snippet.trim();

@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//简介定义了很多的静态字符串目的就是为了提供jsonObject中相应字符串的"key"。把这些静态的定义单独写到了一个类里面,这是非常好的编程规范
package net.micode.notes.tool;
//这个类就是定义了一堆static string实际就是为jsonObject提供Key把这些定义全部写到一个类里方便查看管理是一个非常好的编程习惯
public class GTaskStringUtils {
public final static String GTASK_JSON_ACTION_ID = "action_id";

@ -15,6 +15,20 @@
*/
package net.micode.notes.tool;
/*使
* R.java
* R.id
* R.drawable 使
* R.layout
* R.menu
* R.String
* R.style 使
* idgetXXX
*
*
* @BG_DEFAULT_COLOR
* BG_DEFAULT_FONT_SIZE
*/
import android.content.Context;
import android.preference.PreferenceManager;
@ -65,6 +79,7 @@ public class ResourceParser {
}
}
//直接获取默认的背景颜色。看不太懂这个PREFERENCE_SET_BG_COLOR_KEY是个final string,也就是说getBoolean肯定执行else
public static int getDefaultBgId(Context context) {
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) {
@ -162,6 +177,7 @@ public class ResourceParser {
R.style.TextAppearanceSuper
};
//这里有一个容错的函数防止输入的id大于资源总量若如此则自动返回默认的设置结果
public static int getTexAppearanceResource(int id) {
/**
* HACKME: Fix bug of store the resource id in shared preference.

@ -0,0 +1 @@
红红火火恍恍惚惚嘟嘟嘟顶顶顶顶嘎嘎嘎啊
Loading…
Cancel
Save