From 1054df25521f0735ff5f906936b1e9bbf77d257e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=A2=E6=88=90=E6=89=AC?= <1329310186@qq.com> Date: Tue, 11 Apr 2023 12:06:37 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E5=BA=A6=E6=8A=A5=E5=91=8A=EF=BC=88?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../7.5/executionHistory/executionHistory.bin | Bin 392815 -> 392815 bytes .../executionHistory/executionHistory.lock | Bin 17 -> 17 bytes .../.gradle/7.5/fileHashes/fileHashes.bin | Bin 198651 -> 198651 bytes .../.gradle/7.5/fileHashes/fileHashes.lock | Bin 17 -> 17 bytes .../7.5/fileHashes/resourceHashesCache.bin | Bin 22713 -> 22747 bytes .../buildOutputCleanup.lock | Bin 17 -> 17 bytes src/Notes-master3/.gradle/file-system.probe | Bin 8 -> 8 bytes .../currentProject/dirs_bucket_0/graph.bin | Bin 1101 -> 1101 bytes .../currentProject/dirs_bucket_1/graph.bin | Bin 2005 -> 2005 bytes .../currentProject/dirs_bucket_2/graph.bin | Bin 950 -> 950 bytes .../currentProject/dirs_bucket_3/graph.bin | Bin 1139 -> 1139 bytes .../dex/debug/mergeDexDebug/classes.dex | Bin 192516 -> 192520 bytes .../tmp/debug/dex-renamer-state.txt | 2 +- .../net/micode/notes/data/NotesProvider.class | Bin 9459 -> 9459 bytes .../net/micode/notes/data/NotesProvider.dex | Bin 8024 -> 8024 bytes .../previous-compilation-data.bin | Bin 13232 -> 13232 bytes .../net/micode/notes/data/NotesProvider.java | 85 +++--- .../notes/gtask/remote/GTaskManager.java | 280 ++++++++++-------- .../java/net/micode/notes/model/Note.java | 93 +++--- .../net/micode/notes/model/WorkingNote.java | 129 ++++---- 20 files changed, 318 insertions(+), 271 deletions(-) diff --git a/src/Notes-master3/.gradle/7.5/executionHistory/executionHistory.bin b/src/Notes-master3/.gradle/7.5/executionHistory/executionHistory.bin index 1deca338b1bf6e47d05a65d9f12595997b6250d4..fc7274f44eb78fd2baa4af24eca992c87e70d75e 100644 GIT binary patch delta 998 zcmaF=NBsRC@rEso-2zH^CbH z5BDRzhW}(vq*i1i7T+D|Mx zbn5drgU_DK3<75YD?Pe1<>J)KlUC-NFn!%FWy|Ox>?s-U`26U~gCdeE{-dX*Ij>ipb%eo;?pUsSBk!S{r)o8?JAEz_`7xm9dzEqiw}$pcmgU zO+WaDMPxc}A7h`$i?WXY%%%(GU;g&tfM?{Q!(SJj{ycqsA7hpBvyZ;Y?w=DrZolW_ z=AifBE6^X)mMG=!&knBXl8U*aG3{IXbf1343dwCeDm+cU&fn_|NK&`_`D5d!&n`7(+FpN;QIkjDjP}a3zALk1W*GguW3=X_`t-yJjNsHDy#3xQ#=bxS z3F+C1U0o_%Vrd_??`nB^eEP)uj6u`qKWA0k{@#X3pGgNj3>W(rC+a{QJ$?O5R@Uhi zTUg7dPgupoJ>5@%k#l;!Dy#GM{j*q&yfD)e<5Si>tlH?I(Ec3chZ}Z4FEr2jHGlEv zgHJNoR-NZkzNS9C&z(hfJL_xKS|Lx4t{?gw$3B&5#I-eNb zKTI=H<5Pe_jcYsgKfW*A>Q`LTczBNp7f=WzPz$42B&Pd5XAPRJAH!n7R1yjR5DTgB delta 848 zcmaF=NBsRC@rEso-2#&j%~4>I;GP~J$mqIVdlr)c>vknE#x70)3z2I+r3?02+_>zW z5>mo6efmcpCgJG@E11N$Ka*#?BPn>FwN>`W;k5GhRgNMGd)?stbXCbpLR?gR=kZoWLF+pN@d%B@9_{p$?3 z1BG6mZ!L@!0xE3_56CUJ`k?pG!b#C< z4&2*b*UDJT!Le%AW}r9TF-<@Chec#MZy#fyh>$|k{eq$e&hDNvlf5-uLiWtud~^Ex zKE^8LFH*5f4tOp6IkmVjc(UkS51?E7>$IZoo)*_}=3BNpc;DqG(|!6GDCRWv!M1#!=rCQ;fLUVt*M49C!fXZ_vhvd2JyvsPe>odr!tSp4J94|i z1ja4iAYZXCwlf@@UO0(KXY!w=YMak4HD%gfe~(d3`ms)*c%Lz7`uyjtire4YFzGYtpoi0w zsi2@}dB6>H5qfB~d)YGqF*6XeZ1=Kfz2yZCa{=$^|HWCOxBnAot!CUV)5AK8clr($ zR_o~%TUg7dPgupoJ>5@%k#l;!Dy#GM{j*q&yf7n|@hR&bR&8|eESLy#%nduBTP_Dw ztm@+wJHny5zMbW;`Gx6y?kuv~Szoi(3VEuZuAJU)nWGUVVaI#Yyi@dK>Mfwqebdtm+)i;aY?A(ATA`CV4=98YI)zaz64QO3vj$Dqk72Q3DhUMu DENO51 diff --git a/src/Notes-master3/.gradle/7.5/executionHistory/executionHistory.lock b/src/Notes-master3/.gradle/7.5/executionHistory/executionHistory.lock index 200ce250a0c6a242633e43749c26cf5fe35db1a8..9a73260024fe4571905b0d114bd3ddb9aa11bed6 100644 GIT binary patch literal 17 VcmZQRux5)(aDJ>d0~jz@0st}b1TFvo literal 17 VcmZQRux5)(aDJ>d0~jzz0RS=51P=fJ diff --git a/src/Notes-master3/.gradle/7.5/fileHashes/fileHashes.bin b/src/Notes-master3/.gradle/7.5/fileHashes/fileHashes.bin index 201b084a4fa79ecaf259f6b43ca0da6caa7c734b..fd4de212203b3a96ad07f8139b0fead982e3ac68 100644 GIT binary patch delta 283 zcmey}&-1&Vr=f*$3)5{W1&h*n+iC`b*T1&)t}H#1SH-}<*q&E-t%Cs!Ow6Yr6k`J%PGNrrbZ&idAj9l~t z%>~nP)YwAGCT)496LzZcGeqrvC9qni4;<6idoYzryeRAV&uqG2{^f5U4tPc`It)>D zv2?qwCsWNnmb{`XY}0kwn59&<@u=`L{W^cIHy}yf^5>6@5QUdNfsGT)e+;Dc0O`+a A6#xJL delta 268 zcmey}&-1&Vr=f*$3)5{W1%;4o5k>EFCvROn^0tKgP#6OPV|%vD-?I#0p#Ng}K`}<* z?R?Tqx}4MBrZS4KWb3TeoGjQNwLMpb>5PDc>b++Q2ai@TXD*uLeCxqnMX-LI9gf=r zO_>~+6ioIM`c8XLU3=K@fwY{@4}OUBi3JejRdH@CtUvU5c diff --git a/src/Notes-master3/.gradle/7.5/fileHashes/fileHashes.lock b/src/Notes-master3/.gradle/7.5/fileHashes/fileHashes.lock index 2c28c6f794ddd8d26a179d809654e529cba38f90..fc6b7b91abe4714bea2c22f2c8973ce9d680ac4c 100644 GIT binary patch literal 17 UcmZQRS;(HBDtIuD0Sttt04kRQh5!Hn literal 17 UcmZQRS;(HBDtIuD0StsW0V;+AbpQYW diff --git a/src/Notes-master3/.gradle/7.5/fileHashes/resourceHashesCache.bin b/src/Notes-master3/.gradle/7.5/fileHashes/resourceHashesCache.bin index 049c29610b931afd9eea9865f2de497176a369b8..6a30a969115f4992c6361570c446be201595e3e2 100644 GIT binary patch delta 87 zcmdnFk@5CM#tkMCjJ2ChB?PzyG9|Kgf&**<8NeW7=VV*u#f&F6D*h1PXb`}&+0mmy iK*<;=Cke!YAS`gCwE8Hw&Ya1Q^eetPa~4Pg1?2!+OBgEv delta 35 rcmcb;k#Xln#tkMCj5V80B?P!9$12Ze+_+KkhxkT=44%!79u)!r^9Ky) diff --git a/src/Notes-master3/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/src/Notes-master3/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 687d29e769c90765f121a3541a2a3be4a870bd5e..4ff5adeffef02253f629b4af353af2fded8d9c29 100644 GIT binary patch literal 17 UcmZSn8eGv@J-bDe0SuU%0W_TiegFUf literal 17 UcmZSn8eGv@J-bDe0SuT60W^yQYybcN diff --git a/src/Notes-master3/.gradle/file-system.probe b/src/Notes-master3/.gradle/file-system.probe index bbf5236adc67e5a2be2bfdc4a1950aba146d4753..43c30ca90a60e799b3d0df8c05a1e2ddfbbd5de0 100644 GIT binary patch literal 8 PcmZQzU~JDTnqUtA2Oa`A literal 8 PcmZQzU~JFU>2Lx71~UQb diff --git a/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_0/graph.bin b/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_0/graph.bin index 9e8226702b02e480e72de3d5a3ebb3aa67596ea0..61460b4b9ddf5d92b2ee817f9adc0f71af0a11b5 100644 GIT binary patch delta 38 pcmX@hah78P2NNUHWKO27jEs}_Go1pmyO_80FxopXfI&qC0|3pY2{8Zw delta 38 ncmX@hah78P2NR>fWKO27Kyp9RDInR!yq!nD-hlxODk>NN(qai~ diff --git a/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_1/graph.bin b/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_1/graph.bin index 3106ce2e69348e294de7b3ec3d826557cdf47577..69b343dae689324e7a753f27f8974ae68d7b713f 100644 GIT binary patch delta 124 zcmcc0f0cg&BNHc+y#oUXFix&z?wmZCNrjPd@(!joj4YE=nU4b5+AP~RS)gi|Cik<> rnB2sASeg+k!cbAjP{$xs3?jM8dBEl*ux&;$wQlk(c6}a%jtT|<;0qcE delta 124 zcmcc0f0cg&BNL~9y#oUXFix&z?wmZCNrh2h@(!joKr)s2D3H`<*#=j`G`XL3#^ff} r!_qKa3>Ae8bqq4aAd;(`2WXDKn6`)*XKd#s9*p90bm-3 diff --git a/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_2/graph.bin b/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_2/graph.bin index 174864db80d0aa759736567fdb027009da471e84..2a8871f6f0ed698c5146815e753b4db9ba86e9f3 100644 GIT binary patch delta 25 gcmdnSzKwl@91|ncWO=5ojEs}7G93l7XERF!0AKzGHvj+t delta 25 ecmdnSzKwl@9229!WO=5oK=LZnQ6M>+SsDOg*9T$% diff --git a/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_3/graph.bin b/src/Notes-master3/app/build/intermediates/desugar_graph/debug/out/currentProject/dirs_bucket_3/graph.bin index 610b55c348b1785c0e144c64249ae41fbdcddec9..fc1792614ddf3f0cec90e95a7c8a0583b1cc030f 100644 GIT binary patch delta 38 pcmey&@tI?T0uv+CWJRWfjEs{XGo1jk*D&wqVYGK(0E3DO1_0#R3IPBB delta 38 ocmey&@tI?T0u!UaWJRWfK=Luu2_U(Kc{h)My#oUnR8%kk0O^(rI{*Lx diff --git a/src/Notes-master3/app/build/intermediates/dex/debug/mergeDexDebug/classes.dex b/src/Notes-master3/app/build/intermediates/dex/debug/mergeDexDebug/classes.dex index 60c57e430a116cb9253a56bde2abf9a68b68ddf1..0d31429de816c55d4c588849eabb0f87fc43a80b 100644 GIT binary patch delta 24127 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 X&VDeGSO4Wge|DphSLYVQUz+|8t_*KH delta 24042 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 L8od7Yga!Wq?n9vS delta 648 zcmXAn3rr1Q7>1uWE84LgifT%8lqR>$YA(qZvdI)PY?SL{B%RHJLockgquuXc?Q59}a&WH*n zmokWB4COenlrxJHB--?3PLXN^nVjVS=P01kswysU5iix$Ti&3Sdq((#I+`t8@Osk2 zT9tdvRIlS_51ia2fLl!Cwza!sl6Ot6!QdOo;~|ASqL?Nscub9Doi+3F)LuWc*3I1K zxt$ied11OO{I*5(^Gc#sVYHccyP|llSl%juckBhyJP*R#mD^zuod)s2Ai4~q+aNwN zn@=p{GmGhAt!*)bFC646Zp%^|QN|C>^V95pafv^M-)8{*w)Z~X^Op`mmwenc2iR8E=T}^U&dR&2;8;C>02-I*w6-0!B8LtpxG=c<$GEXB(Q8-&P ziXCQ@r_q!vf=bI8jlrw2G$`6VKcZTb+}|TkyQbKuno5ufxtPub;;fosYVo8nlNBs* I*GIlBf+=CFQy7~V zyBT{J`x*JNn0dmuGnsi~dE}Y-3PhPq4>2V&O7aEBF*CO_idHN?nw@EIc)OMyGeeRP zql^G615=s~D>G9?+m;Xak1$orG71U+NhFSutnOBZIg_Ue${F!5VX6R{)jl1lv7M<* zww;MzHgl<`gEtT}_%ZM;WjMmfJO%6$KA;5=O!AYT3EDG$nXD${uDF+paS9_J!yG1{ xJRgG&17AmbCI~PIL^4P*@G&f$+$W^TXuo-fPy;uId77nxNvgTgW(PS5MgZ4%NrM0Y delta 266 zcmca%cf(F0CAEUfz}S>wH6U z7-a-l8JIG3SecnB+qQhTe}t)0mQhduNFs6cWOcVP%$Ph)P|k>V2~!2otoG?ZjqOb3 zvh7T~vYAUg9lV!%+B1YO@GWK7#mGDb>=Hhp1rbbglb;FNGrpLtCgiTTj)`#!BOgOQ z6HuOy!Hj{gy*(2InD`?Z)EM{}CQt4Y(qy#TyhEsgn*;|hR6;kR=19O~APbE%d!%%7oeI<0Th4j!$Ey51tAfIfd${KOELhpk9 zLGqV|(Uc(1wy-j`rEx==8PHESqkXDNT8#r)S!$T_UD|O$=N)_(=qbUc=?^T1xJM1z zyG5#~o=x{<%yjScqb>jk(s3#szRau0^fHobi(Cso;_iYPl;cTfBw5v`!a-7Ub>toG?R($n*Yp0qFc;>+yxsKTe{9#rMZ}T@xIzLsa|+i3$p)=kv3q zKal;qf>D-1o@-LM%tR-G$~bQVJwzH%cR1!vE=i^pEH7X=i8DTpuzSmUu)J$^tMb5( zAR9nD9hnThVzP=G6rr+L=$NG=X$*uoue)5-B|Y#SXXLQRR`3Pg=XNDBFf=OBg)IeM n6*FCMdz-6(A;rT)mqN=I^qZU3ovCj7F$Pt}x|lh7BsK5{okCT> diff --git a/src/Notes-master3/app/src/main/java/net/micode/notes/data/NotesProvider.java b/src/Notes-master3/app/src/main/java/net/micode/notes/data/NotesProvider.java index 288921e..6897999 100644 --- a/src/Notes-master3/app/src/main/java/net/micode/notes/data/NotesProvider.java +++ b/src/Notes-master3/app/src/main/java/net/micode/notes/data/NotesProvider.java @@ -1,22 +1,5 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.data; - import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentUris; @@ -33,9 +16,15 @@ import net.micode.notes.R; import net.micode.notes.data.Notes.DataColumns; import net.micode.notes.data.Notes.NoteColumns; import net.micode.notes.data.NotesDatabaseHelper.TABLE; - - +//为存储和获取数据提供接口。可以在不同的应用程序之间共享数据 +//ContentProvider提供的方法 +//query:查询 +//insert:插入 +//update:更新 +//delete:删除 +//getType:得到数据类型 public class NotesProvider extends ContentProvider { + // UriMatcher用于匹配Uri private static final UriMatcher mMatcher; private NotesDatabaseHelper mHelper; @@ -51,7 +40,9 @@ public class NotesProvider extends ContentProvider { private static final int URI_SEARCH_SUGGEST = 6; static { + // 创建UriMatcher时,调用UriMatcher(UriMatcher.NO_MATCH)表示不匹配任何路径的返回码 mMatcher = new UriMatcher(UriMatcher.NO_MATCH); + // 把需要匹配Uri路径全部给注册上 mMatcher.addURI(Notes.AUTHORITY, "note", URI_NOTE); mMatcher.addURI(Notes.AUTHORITY, "note/#", URI_NOTE_ITEM); mMatcher.addURI(Notes.AUTHORITY, "data", URI_DATA); @@ -62,36 +53,43 @@ public class NotesProvider extends ContentProvider { } /** - * x'0A'表示sqlite中的'\n'字符。对于搜索结果中的标题和内容, - *我们将修剪'\n'和空白以显示更多信息。 - * */ + * x'0A' represents the '\n' character in sqlite. For title and content in the search result, + * we will trim '\n' and white space in order to show more information. + */ + // 声明 NOTES_SEARCH_PROJECTION private static final String NOTES_SEARCH_PROJECTION = NoteColumns.ID + "," - + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," - + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," - + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," - + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," - + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; - + + NoteColumns.ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_1 + "," + + "TRIM(REPLACE(" + NoteColumns.SNIPPET + ", x'0A','')) AS " + SearchManager.SUGGEST_COLUMN_TEXT_2 + "," + + R.drawable.search_result + " AS " + SearchManager.SUGGEST_COLUMN_ICON_1 + "," + + "'" + Intent.ACTION_VIEW + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_ACTION + "," + + "'" + Notes.TextNote.CONTENT_TYPE + "' AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA; + // 声明NOTES_SNIPPET_SEARCH_QUERY private static String NOTES_SNIPPET_SEARCH_QUERY = "SELECT " + NOTES_SEARCH_PROJECTION - + " FROM " + TABLE.NOTE - + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" - + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER - + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; + + " FROM " + TABLE.NOTE + + " WHERE " + NoteColumns.SNIPPET + " LIKE ?" + + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE; @Override + // Context只有在onCreate()中才被初始化 + // 对mHelper进行实例化 public boolean onCreate() { mHelper = NotesDatabaseHelper.getInstance(getContext()); return true; } @Override + // 查询uri在数据库中对应的位置 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { + String sortOrder) { Cursor c = null; + // 获取可读数据库 SQLiteDatabase db = mHelper.getReadableDatabase(); String id = null; + // 匹配查找uri switch (mMatcher.match(uri)) { + // 对于不同的匹配值,在数据库中查找相应的条目 case URI_NOTE: c = db.query(TABLE.NOTE, projection, selection, selectionArgs, null, null, sortOrder); @@ -113,6 +111,7 @@ public class NotesProvider extends ContentProvider { case URI_SEARCH: case URI_SEARCH_SUGGEST: if (sortOrder != null || projection != null) { + // 不合法的参数异常 throw new IllegalArgumentException( "do not specify sortOrder, selection, selectionArgs, or projection" + "with this query"); } @@ -120,6 +119,8 @@ public class NotesProvider extends ContentProvider { String searchString = null; if (mMatcher.match(uri) == URI_SEARCH_SUGGEST) { if (uri.getPathSegments().size() > 1) { + // getPathSegments()方法得到一个String的List, + // 在uri.getPathSegments().get(1)为第2个元素 searchString = uri.getPathSegments().get(1); } } else { @@ -139,6 +140,7 @@ public class NotesProvider extends ContentProvider { } break; default: + // 抛出异常 throw new IllegalArgumentException("Unknown URI " + uri); } if (c != null) { @@ -148,13 +150,17 @@ public class NotesProvider extends ContentProvider { } @Override + // 插入一个uri public Uri insert(Uri uri, ContentValues values) { + // 获得可写的数据库 SQLiteDatabase db = mHelper.getWritableDatabase(); long dataId = 0, noteId = 0, insertedId = 0; switch (mMatcher.match(uri)) { + // 新增一个条目 case URI_NOTE: insertedId = noteId = db.insert(TABLE.NOTE, null, values); break; + // 如果存在,查找NOTE_ID case URI_DATA: if (values.containsKey(DataColumns.NOTE_ID)) { noteId = values.getAsLong(DataColumns.NOTE_ID); @@ -167,6 +173,7 @@ public class NotesProvider extends ContentProvider { throw new IllegalArgumentException("Unknown URI " + uri); } // Notify the note uri + // notifyChange获得一个ContextResolver对象并且更新里面的内容 if (noteId > 0) { getContext().getContentResolver().notifyChange( ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), null); @@ -178,13 +185,17 @@ public class NotesProvider extends ContentProvider { ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), null); } + // 返回插入的uri的路径 return ContentUris.withAppendedId(uri, insertedId); } @Override + // 删除一个uri public int delete(Uri uri, String selection, String[] selectionArgs) { + //Uri代表要操作的数据,Android上可用的每种资源 -包括 图像、视频片段、音频资源等都可以用Uri来表示。 int count = 0; String id = null; + // 获得可写的数据库 SQLiteDatabase db = mHelper.getWritableDatabase(); boolean deleteData = false; switch (mMatcher.match(uri)) { @@ -228,6 +239,7 @@ public class NotesProvider extends ContentProvider { } @Override + // 更新一个uri public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; String id = null; @@ -267,10 +279,12 @@ public class NotesProvider extends ContentProvider { return count; } + // 将字符串解析成规定格式 private String parseSelection(String selection) { return (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""); } + //增加一个noteVersion private void increaseNoteVersion(long id, String selection, String[] selectionArgs) { StringBuilder sql = new StringBuilder(120); sql.append("UPDATE "); @@ -293,6 +307,7 @@ public class NotesProvider extends ContentProvider { sql.append(selectString); } + // execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句 mHelper.getWritableDatabase().execSQL(sql.toString()); } @@ -302,4 +317,4 @@ public class NotesProvider extends ContentProvider { return null; } -} +} \ No newline at end of file diff --git a/src/Notes-master3/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/src/Notes-master3/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java index d2b4082..a8c1f2a 100644 --- a/src/Notes-master3/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java +++ b/src/Notes-master3/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java @@ -1,119 +1,73 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.gtask.remote; -import android.app.Activity; -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.util.Log; - -import net.micode.notes.R; -import net.micode.notes.data.Notes; -import net.micode.notes.data.Notes.DataColumns; -import net.micode.notes.data.Notes.NoteColumns; -import net.micode.notes.gtask.data.MetaData; -import net.micode.notes.gtask.data.Node; -import net.micode.notes.gtask.data.SqlNote; -import net.micode.notes.gtask.data.Task; -import net.micode.notes.gtask.data.TaskList; -import net.micode.notes.gtask.exception.ActionFailureException; -import net.micode.notes.gtask.exception.NetworkFailureException; -import net.micode.notes.tool.DataUtils; -import net.micode.notes.tool.GTaskStringUtils; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; - - public class GTaskManager { private static final String TAG = GTaskManager.class.getSimpleName(); - public static final int STATE_SUCCESS = 0; - public static final int STATE_NETWORK_ERROR = 1; - public static final int STATE_INTERNAL_ERROR = 2; - public static final int STATE_SYNC_IN_PROGRESS = 3; - public static final int STATE_SYNC_CANCELLED = 4; - private static GTaskManager mInstance = null; private Activity mActivity; - private Context mContext; - private ContentResolver mContentResolver; - private boolean mSyncing; - private boolean mCancelled; - private HashMap mGTaskListHashMap; - private HashMap mGTaskHashMap; - private HashMap mMetaHashMap; - private TaskList mMetaList; - private HashSet mLocalDeleteIdMap; - private HashMap mGidToNid; - private HashMap mNidToGid; - private GTaskManager() { - mSyncing = false; - mCancelled = false; - mGTaskListHashMap = new HashMap(); + private GTaskManager() { //对象初始化函数 + mSyncing = false; //正在同步,flase代表未执行 + mCancelled = false; //全局标识,flase代表可以执行 + mGTaskListHashMap = new HashMap(); //<>代表Java的泛型,就是创建一个用类型作为参数的类。 mGTaskHashMap = new HashMap(); mMetaHashMap = new HashMap(); mMetaList = null; mLocalDeleteIdMap = new HashSet(); - mGidToNid = new HashMap(); - mNidToGid = new HashMap(); + mGidToNid = new HashMap(); //GoogleID to NodeID?? + mNidToGid = new HashMap(); //NodeID to GoogleID???通过hashmap散列表建立映射 } - public static synchronized GTaskManager getInstance() { + /** + * 包含关键字synchronized,语言级同步,指明该函数可能运行在多线程的环境下。 + * 功能:类初始化函数 + * @author TTS + * @return GtaskManger + */ + public static synchronized GTaskManager getInstance() { //可能运行在多线程环境下,使用语言级同步--synchronized if (mInstance == null) { mInstance = new GTaskManager(); } return mInstance; } + /** + * 包含关键字synchronized,语言级同步,指明该函数可能运行在多线程的环境下。 + * @author TTS + * @param activity + */ public synchronized void setActivityContext(Activity activity) { - // used for getting authtoken + // used for getting auth token mActivity = activity; } - public int sync(Context context, GTaskASyncTask asyncTask) { + /** + * 核心函数 + * 功能:实现了本地同步操作和远端同步操作 + * @author TTS + * @param context-----获取上下文 + * @param asyncTask-------用于同步的异步操作类 + * @return int + */ + 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 +82,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 +94,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,32 +122,41 @@ public class GTaskManager { return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; } + /** + *功能:初始化GtaskList,获取Google上的JSONtasklist转为本地TaskList。 + *获得的数据存储在mMetaList,mGTaskListHashMap,mGTaskHashMap + *@author TTS + *@exception NetworkFailureException + *@return void + */ private void initGTaskList() throws NetworkFailureException { if (mCancelled) return; - GTaskClient client = GTaskClient.getInstance(); + GTaskClient client = GTaskClient.getInstance(); //getInstance即为创建一个实例,client应指远端客户机 try { - JSONArray jsTaskLists = client.getTaskLists(); + //Json对象是Name Value对(即子元素)的无序集合,相当于一个Map对象。JsonObject类是bantouyan-json库对Json对象的抽象,提供操纵Json对象的各种方法。 + //其格式为{"key1":value1,"key2",value2....};key 必须是字符串。 + //因为ajax请求不刷新页面,但配合js可以实现局部刷新,因此json常常被用来作为异步请求的返回对象使用。 + JSONArray jsTaskLists = client.getTaskLists(); //原注释为get task list------lists??? // 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); + if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { + mMetaList = new TaskList(); //MetaList意为元表,Tasklist类型,此处为初始化 + mMetaList.setContentByRemoteJSON(object); //将JSON中部分数据复制到自己定义的对象中相对应的数据:name->mname... // load meta data - JSONArray jsMetas = client.getTaskList(gid); + JSONArray jsMetas = client.getTaskList(gid); //原注释为get action_list------list??? 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()) { + if (metaData.isWorthSaving()) { //if not worth to save,metadata将不加入mMetaList mMetaList.addChildTask(metaData); if (metaData.getGid() != null) { mMetaHashMap.put(metaData.getRelatedGid(), metaData); @@ -214,16 +177,16 @@ public class GTaskManager { // init task list for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); - String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); + String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); //通过getString函数传入本地某个标志数据的名称,获取其在远端的名称。 String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_META)) { - TaskList tasklist = new TaskList(); + + GTaskStringUtils.FOLDER_META)) { + TaskList tasklist = new TaskList(); //继承自Node tasklist.setContentByRemoteJSON(object); mGTaskListHashMap.put(gid, tasklist); - mGTaskHashMap.put(gid, tasklist); + mGTaskHashMap.put(gid, tasklist); //为什么加两遍??? // load tasks JSONArray jsTasks = client.getTaskList(gid); @@ -247,13 +210,18 @@ public class GTaskManager { } } - private void syncContent() throws NetworkFailureException { + /** + * 功能:本地内容同步操作 + * @throws NetworkFailureException + * @return 无返回值 + */ + private void syncContent() throws NetworkFailureException { //本地内容同步操作 int syncType; - Cursor c = null; - String gid; - Node node; + Cursor c = null; //数据库指针 + String gid; //GoogleID?? + Node node; //Node包含Sync_Action的不同类型 - mLocalDeleteIdMap.clear(); + mLocalDeleteIdMap.clear(); //HashSet类型 if (mCancelled) { return; @@ -301,8 +269,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,14 +295,14 @@ public class GTaskManager { } // go through remaining items - Iterator> iter = mGTaskHashMap.entrySet().iterator(); + Iterator> iter = mGTaskHashMap.entrySet().iterator(); //Iterator迭代器 while (iter.hasNext()) { Map.Entry entry = iter.next(); node = entry.getValue(); doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); } - // mCancelled can be set by another thread, so we neet to check one by + // mCancelled can be set by another thread, so we neet to check one by //thread----线程 // one // clear local delete table if (!mCancelled) { @@ -351,6 +319,11 @@ public class GTaskManager { } + /** + * 功能: + * @author TTS + * @throws NetworkFailureException + */ private void syncFolder() throws NetworkFailureException { Cursor c = null; String gid; @@ -394,7 +367,7 @@ public class GTaskManager { try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", new String[] { - String.valueOf(Notes.ID_CALL_RECORD_FOLDER) + String.valueOf(Notes.ID_CALL_RECORD_FOLDER) }, null); if (c != null) { if (c.moveToNext()) { @@ -476,6 +449,14 @@ public class GTaskManager { GTaskClient.getInstance().commitUpdate(); } + /** + * 功能:syncType分类,addLocalNode,addRemoteNode,deleteNode,updateLocalNode,updateRemoteNode + * @author TTS + * @param syncType + * @param node + * @param c + * @throws NetworkFailureException + */ private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -522,6 +503,12 @@ public class GTaskManager { } } + /** + * 功能:本地增加Node + * @author TTS + * @param node + * @throws NetworkFailureException + */ private void addLocalNode(Node node) throws NetworkFailureException { if (mCancelled) { return; @@ -596,6 +583,15 @@ public class GTaskManager { updateRemoteMeta(node.getGid(), sqlNote); } + /** + * 功能:update本地node + * @author TTS + * @param node + * ----同步操作的基础数据类型 + * @param c + * ----Cursor + * @throws NetworkFailureException + */ private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -619,12 +615,22 @@ public class GTaskManager { updateRemoteMeta(node.getGid(), sqlNote); } + /** + * 功能:远程增加Node + * 需要updateRemoteMeta + * @author TTS + * @param node + * ----同步操作的基础数据类型 + * @param c + * --Cursor + * @throws NetworkFailureException + */ 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 +640,12 @@ 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"); } - mGTaskListHashMap.get(parentGid).addChildTask(task); + mGTaskListHashMap.get(parentGid).addChildTask(task); //在本地生成的GTaskList中增加子结点 + //登录远程服务器,创建Task GTaskClient.getInstance().createTask(task); n = (Node) task; @@ -656,6 +663,7 @@ public class GTaskManager { else folderName += sqlNote.getSnippet(); + //iterator迭代器,通过统一的接口迭代所有的map元素 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -687,11 +695,20 @@ public class GTaskManager { sqlNote.resetLocalModified(); sqlNote.commit(true); - // gid-id mapping + // gid-id mapping //创建id间的映射 mGidToNid.put(n.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), n.getGid()); } + /** + * 功能:更新远端的Node,包含meta更新(updateRemoteMeta) + * @author TTS + * @param node + * ----同步操作的基础数据类型 + * @param c + * --Cursor + * @throws NetworkFailureException + */ private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; @@ -701,7 +718,7 @@ public class GTaskManager { // update remotely node.setContentByLocalJSON(sqlNote.getContent()); - GTaskClient.getInstance().addUpdateNode(node); + GTaskClient.getInstance().addUpdateNode(node); //GTaskClient用途为从本地登陆远端服务器 // update meta updateRemoteMeta(node.getGid(), sqlNote); @@ -710,15 +727,19 @@ 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) { + if (preParentList != curParentList) { //????????????? preParentList.removeChildTask(task); curParentList.addChildTask(task); GTaskClient.getInstance().moveTask(task, preParentList, curParentList); @@ -727,9 +748,19 @@ public class GTaskManager { // clear local modified flag sqlNote.resetLocalModified(); + //commit到本地数据库 sqlNote.commit(true); } + /** + * 功能:升级远程meta。 meta---元数据----计算机文件系统管理数据---管理数据的数据。 + * @author TTS + * @param gid + * ---GoogleID为String类型 + * @param sqlNote + * ---同步前的数据库操作,故使用类SqlNote + * @throws NetworkFailureException + */ private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { if (sqlNote != null && sqlNote.isNoteType()) { MetaData metaData = mMetaHashMap.get(gid); @@ -746,12 +777,18 @@ public class GTaskManager { } } + /** + * 功能:刷新本地,给sync的ID对应上最后更改过的对象 + * @author TTS + * @return void + * @throws NetworkFailureException + */ private void refreshLocalSyncId() throws NetworkFailureException { if (mCancelled) { return; } - // get the latest gtask list + // get the latest gtask list //获取最近的(最晚的)gtask list mGTaskHashMap.clear(); mGTaskListHashMap.clear(); mMetaHashMap.clear(); @@ -762,16 +799,16 @@ public class GTaskManager { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(type<>? AND parent_id<>?)", new String[] { String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); + }, NoteColumns.TYPE + " DESC"); //query语句:五个参数,NoteColumns.TYPE + " DESC"-----为按类型递减顺序返回查询结果。new String[] {String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)}------为选择参数。"(type<>? AND parent_id<>?)"-------指明返回行过滤器。SqlNote.PROJECTION_NOTE--------应返回的数据列的名字。Notes.CONTENT_NOTE_URI--------contentProvider包含所有数据集所对应的uri if (c != null) { while (c.moveToNext()) { String gid = c.getString(SqlNote.GTASK_ID_COLUMN); Node node = mGTaskHashMap.get(gid); if (node != null) { mGTaskHashMap.remove(gid); - ContentValues values = new ContentValues(); + ContentValues values = new ContentValues(); //在ContentValues中创建键值对。准备通过contentResolver写入数据 values.put(NoteColumns.SYNC_ID, node.getLastModified()); - mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, + mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, //进行批量更改,选择参数为NULL,应该可以用insert替换,参数分别为表名和需要更新的value对象。 c.getLong(SqlNote.ID_COLUMN)), values, null, null); } else { Log.e(TAG, "something is missed"); @@ -790,11 +827,20 @@ public class GTaskManager { } } + /** + * 功能:获取同步账号,mAccount.name + * @author TTS + * @return String + */ public String getSyncAccount() { return GTaskClient.getInstance().getSyncAccount().name; } + /** + * 功能:取消同步,置mCancelled为true + * @author TTS + */ public void cancelSync() { mCancelled = true; } -} +} \ No newline at end of file diff --git a/src/Notes-master3/app/src/main/java/net/micode/notes/model/Note.java b/src/Notes-master3/app/src/main/java/net/micode/notes/model/Note.java index 6706cf6..d1f1de4 100644 --- a/src/Notes-master3/app/src/main/java/net/micode/notes/model/Note.java +++ b/src/Notes-master3/app/src/main/java/net/micode/notes/model/Note.java @@ -1,43 +1,21 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - 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 net.micode.notes.data.Notes; -import net.micode.notes.data.Notes.CallNote; -import net.micode.notes.data.Notes.DataColumns; -import net.micode.notes.data.Notes.NoteColumns; -import net.micode.notes.data.Notes.TextNote; - -import java.util.ArrayList; +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;//输出日志,比如说出错、警告等 public class Note { - private ContentValues mNoteDiffValues; + // private ContentValues mNoteDiffValues; + ContentValues mNoteDiffValues;// private NoteData mNoteData; private static final String TAG = "Note"; + /** * Create a new note id for adding a new note to databases */ @@ -49,16 +27,17 @@ 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 { noteId = Long.valueOf(uri.getPathSegments().get(1)); } catch (NumberFormatException e) { Log.e(TAG, "Get note id error :" + e.toString()); noteId = 0; - } + }//try-catch异常处理 if (noteId == -1) { throw new IllegalStateException("Wrong note id:" + noteId); } @@ -68,37 +47,37 @@ public class Note { 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); - } + }//设置数据库表格的标签文本内容的数据 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); - } + }//得到电话号码数据的ID public boolean isLocalModified() { return mNoteDiffValues.size() > 0 || mNoteData.isLocalModified(); - } + }//判断是否是本地修改 public boolean syncNote(Context context, long noteId) { if (noteId <= 0) { @@ -128,16 +107,16 @@ public class Note { } return true; - } + }//判断数据是否同步 - private class NoteData { + 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"; @@ -147,7 +126,7 @@ public class Note { mTextDataId = 0; mCallDataId = 0; } - + //下面是上述几个函数的具体实现 boolean isLocalModified() { return mTextDataValues.size() > 0 || mCallDataValues.size() > 0; } @@ -177,17 +156,17 @@ public class Note { mNoteDiffValues.put(NoteColumns.LOCAL_MODIFIED, 1); 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 operationList = new ArrayList(); - ContentProviderOperation.Builder builder = null; + ContentProviderOperation.Builder builder = null;//数据库的操作列表 if(mTextDataValues.size() > 0) { mTextDataValues.put(DataColumns.NOTE_ID, noteId); @@ -209,7 +188,7 @@ public class Note { operationList.add(builder.build()); } mTextDataValues.clear(); - } + }//把文本数据存入DataColumns if(mCallDataValues.size() > 0) { mCallDataValues.put(DataColumns.NOTE_ID, noteId); @@ -231,7 +210,7 @@ public class Note { operationList.add(builder.build()); } mCallDataValues.clear(); - } + }//把电话号码数据存入DataColumns if (operationList.size() > 0) { try { @@ -246,8 +225,8 @@ public class Note { Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); return null; } - } + }//存储过程中的异常处理 return null; } } -} +} \ No newline at end of file diff --git a/src/Notes-master3/app/src/main/java/net/micode/notes/model/WorkingNote.java b/src/Notes-master3/app/src/main/java/net/micode/notes/model/WorkingNote.java index be081e4..cbb0754 100644 --- a/src/Notes-master3/app/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/src/Notes-master3/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -1,37 +1,5 @@ -/* - * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package net.micode.notes.model; -import android.appwidget.AppWidgetManager; -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.text.TextUtils; -import android.util.Log; - -import net.micode.notes.data.Notes; -import net.micode.notes.data.Notes.CallNote; -import net.micode.notes.data.Notes.DataColumns; -import net.micode.notes.data.Notes.DataConstants; -import net.micode.notes.data.Notes.NoteColumns; -import net.micode.notes.data.Notes.TextNote; -import net.micode.notes.tool.ResourceParser.NoteBgResources; - - public class WorkingNote { // Note for the working note private Note mNote; @@ -43,17 +11,11 @@ public class WorkingNote { private int mMode; private long mAlertDate; - private long mModifiedDate; - private int mBgColorId; - private int mWidgetId; - private int mWidgetType; - private long mFolderId; - private Context mContext; private static final String TAG = "WorkingNote"; @@ -62,6 +24,7 @@ public class WorkingNote { private NoteSettingChangedListener mNoteSettingStatusListener; + // 声明 DATA_PROJECTION字符串数组 public static final String[] DATA_PROJECTION = new String[] { DataColumns.ID, DataColumns.CONTENT, @@ -72,6 +35,7 @@ public class WorkingNote { DataColumns.DATA4, }; + // 声明 NOTE_PROJECTION字符串数组 public static final String[] NOTE_PROJECTION = new String[] { NoteColumns.PARENT_ID, NoteColumns.ALERTED_DATE, @@ -82,27 +46,18 @@ public class WorkingNote { }; private static final int DATA_ID_COLUMN = 0; - private static final int DATA_CONTENT_COLUMN = 1; - private static final int DATA_MIME_TYPE_COLUMN = 2; - private static final int DATA_MODE_COLUMN = 3; - private static final int NOTE_PARENT_ID_COLUMN = 0; - private static final int NOTE_ALERTED_DATE_COLUMN = 1; - private static final int NOTE_BG_COLOR_ID_COLUMN = 2; - private static final int NOTE_WIDGET_ID_COLUMN = 3; - private static final int NOTE_WIDGET_TYPE_COLUMN = 4; - private static final int NOTE_MODIFIED_DATE_COLUMN = 5; // New note construct - private WorkingNote(Context context, long folderId) { + public WorkingNote(Context context, long folderId) { mContext = context; mAlertDate = 0; mModifiedDate = System.currentTimeMillis(); @@ -114,7 +69,9 @@ public class WorkingNote { mWidgetType = Notes.TYPE_WIDGET_INVALIDE; } + // WorkingNote的构造函数 // Existing note construct + private WorkingNote(Context context, long noteId, long folderId) { mContext = context; mNoteId = noteId; @@ -124,11 +81,14 @@ 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,6 +99,7 @@ public class WorkingNote { mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN); } cursor.close(); + // 若不存在,报错 } else { Log.e(TAG, "No note with id:" + mNoteId); throw new IllegalArgumentException("Unable to find note with id " + mNoteId); @@ -146,14 +107,16 @@ public class WorkingNote { loadNoteData(); } + // 加载NoteData private void loadNoteData() { Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { - String.valueOf(mNoteId) + String.valueOf(mNoteId) }, 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 +128,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 +137,12 @@ public class WorkingNote { } } + // 创建空的Note + // 传参:context,文件夹id,widget,背景颜色 public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId, - int widgetType, int defaultBgColorId) { + int widgetType, int defaultBgColorId) { WorkingNote note = new WorkingNote(context, folderId); + // 设定相关属性 note.setBgColorId(defaultBgColorId); note.setWidgetId(widgetId); note.setWidgetType(widgetType); @@ -187,9 +153,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 +179,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 +195,14 @@ 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,16 +213,20 @@ 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(); + // 调用mNoteSettingStatusListener的 onWidgetChanged方法 } } + // 设定背景颜色 public void setBgColorId(int id) { - if (id != mBgColorId) { + if (id != mBgColorId) { //设定条件 id != mBgColorId mBgColorId = id; if (mNoteSettingStatusListener != null) { mNoteSettingStatusListener.onBackgroundColorChanged(); @@ -257,8 +235,10 @@ public class WorkingNote { } } + // 设定检查列表模式 + // 参数:mode public void setCheckListMode(int mode) { - if (mMode != mode) { + if (mMode != mode) { //设定条件 mMode != mode if (mNoteSettingStatusListener != null) { mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode); } @@ -267,81 +247,108 @@ public class WorkingNote { } } + + // 设定WidgetType + // 参数:type public void setWidgetType(int type) { - if (type != mWidgetType) { + if (type != mWidgetType) {//设定条件 type != mWidgetType mWidgetType = type; mNote.setNoteValue(NoteColumns.WIDGET_TYPE, String.valueOf(mWidgetType)); + // 调用Note的setNoteValue方法更改WidgetType } } + // 设定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 @@ -365,4 +372,4 @@ public class WorkingNote { */ void onCheckListModeChanged(int oldMode, int newMode); } -} +} \ No newline at end of file