From 8e050b9c4532772e236dd3faf57dcd15695dfaac Mon Sep 17 00:00:00 2001 From: pj36foInf <445038096@qq.com> Date: Fri, 14 Apr 2023 15:31:17 +0800 Subject: [PATCH 1/8] 414 --- doc/精读报告/data/Contact.doc | Bin 28672 -> 0 bytes doc/精读报告/data/Notes.doc | Bin 40960 -> 0 bytes doc/精读报告/data/NotesDatabaseHelper.doc | Bin 58368 -> 0 bytes doc/精读报告/data/NotesProvider.doc | Bin 52224 -> 0 bytes doc/精读报告/gtask/data/MetaData.doc | 118 ---- doc/精读报告/gtask/data/Node.doc | 104 ---- doc/精读报告/gtask/data/SqlData.doc | 218 ------- doc/精读报告/gtask/data/SqlNote.doc | 566 ------------------ doc/精读报告/gtask/data/Task.doc | 351 ----------- doc/精读报告/gtask/data/TaskList.doc | 401 ------------- 10 files changed, 1758 deletions(-) delete mode 100644 doc/精读报告/data/Contact.doc delete mode 100644 doc/精读报告/data/Notes.doc delete mode 100644 doc/精读报告/data/NotesDatabaseHelper.doc delete mode 100644 doc/精读报告/data/NotesProvider.doc delete mode 100644 doc/精读报告/gtask/data/MetaData.doc delete mode 100644 doc/精读报告/gtask/data/Node.doc delete mode 100644 doc/精读报告/gtask/data/SqlData.doc delete mode 100644 doc/精读报告/gtask/data/SqlNote.doc delete mode 100644 doc/精读报告/gtask/data/Task.doc delete mode 100644 doc/精读报告/gtask/data/TaskList.doc diff --git a/doc/精读报告/data/Contact.doc b/doc/精读报告/data/Contact.doc deleted file mode 100644 index fc86dec7b4d2e5b02e96b40e1938e4c80c816a62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 zcmeHw2V7J~*Y~gs2q=gR72Ara7-3l(APAyZP!wraL|tGh0=ozcl3*c@^x2!4{0N-~Zg@23P?xZ<6o(-e-s3f6vU^nKLuzoICB#y%gj( zxUp`l`Aw$bT$qrRstlQag?JtKyYXRD#(Ka{aiuDiilVy$@M_)vM-q6Hd4%<6hPsRu z`5Yo8G6v1U88Ftp4Pz!OaAM#@36pS%%ve_o#(X9kg%i#pPfbpxs{iNZ>im3y z-JHjyjyg;=^B_t(~=U`c6RkR+ipTzZ+71FtzGZq80zE_s-ee_5ZDuppk zy1zMN0>mExC0ARzuLWbfkTJS7V~%C{`g0sA|L}6)%dLF%-TLt9c*@s@&&TuQDc^4X zI)yJIAb@<#KgvGr6k>KHl4$44|{Odqj)KK}Y9$bn3)8RSZL8QC8>K3z8KfZQacBf0Zo{yKN@Z}{Q) z@~n7$Q8^++@^a=WUp^n^DWAVO%BRz$ygl-?y8L`RUp^nMj%t>}hj}^k;p!;Qm)D~v zecyG>^nX{F*H?A*t}dRh?}yUr_)*^+h>kS65&A3Gw;pSVUqfBp_lyP~TD~^@KOuo= zX;6eTR3?(kl;WuHAVsiDELSLHvEpEUYpQh9KUB0N|eq>w9Ra;4af zXo9ke6qGSg8Y>gK#l^%bVw^NNM8_!N!-Hip91CfXGL~4yz=MdWD22Qq@_U5KgJZ>B zVG6nI1M*YOcake*k+Nto`dH1*GcGDn7BgHK9vS;i(m2G5hbTfTG-{$WUMl9|-KDW% zL#5G9#&1L=mD0;uD6>ZDieVQn zcja>3xbnlm*@@M*%n**h6m6-@U&Q=aA2txN&VYqR3oXh@C@+OtD`IK>gFHw2cS!8& z>4w}x@YkRDu<>jV>xW-ogeb-hya%yi%=2%kW$nu0Tj9mrxpMoXHlA!aB;A**p)bPy znKxpn)>de*h^w11>kOY43*+=FW8zA=%3DvVETE&_tP^~Fkg6XSBjWP+?xAS+ zP?Y4yMuTgAq*3Q|W*xaQHA{2jYU_uTp2$OTB>zzOG&xXy&HB_-6Cc!aB>3u*&_w<1`rluZWrpi1|}c-UHSt@w%90NBkiv{ZyUftUVx zSg8Vk5x5VdE47!e4Nujz5}}3eke3f9=_t<9$FnF-8$sZzwu+9>K}YC~w`nzx@)oNt zd-u%qzVF`675jtA_j1L1RfPLjhI_g4-D>q`SjG}?m3kC)FQN`>-tiSB;Ry*up)Zm_ z(qwUo6?D(bAe@E3l4JiYMcp@*_Yu^3y0_)v6^Xy<`0)H{=0tpC(76Z_r(UtPy_gls zt=L=frA@7(Mddo-Q>k@xH*{KHGr(KG%n++n zpex`6I2tjQ0~7$Jb+LK{{D30hIl!6?WWnrAR39B!Zkf0BJD25ji}uj;=l-Sc{{N#~^R*A-i+4g7loA-Q9> zH#C^k&stS=@6~kQz3*PD={~D?k7-r@@2R|!tTptn9=F^uUy8x#q`)uD*(!!;K2>=Z z$B*3n+)swFONkk&jN=fAwIGdaGz${5N#I2xno+zvYV)HePs>*o{2ZQNB@74uLA4rz z`8iwV8G%0wKs#s+TRuXIG4c+=EZ+<3qdr)@(E6zlMqygROs!Q}@6I!7Ge@YZhUN9E zdgQKcjml@fRm~IL)qr~DVCj?Qe>e2j{GXM7+dGDLo(;mae;Fnl~&8gco zEl}d~dwi_7=DetK`}t61o04O`76o~z=av=Q$KN3p(_3M8zv^`X&z+|=&6#PxhGbr~ zmC*W%uT|~Jsytig^Hya$eC^b76O4Bl_pYw_G*dZU^0Qge{vgyV7_v&h3Yc0j3|7$> z`i zt6GclJk=Wh2rJN#_g<3Mo*)}nn=B> z=XVGkIqj0Bs=gCyZhh_bQ&CRjC;V@6AF|$|wN9nE#Q*)k|0Y%Zdu=J7|JRkUE~ySW zUA+XXP3{b_DEC;Owz&p%EP!^Y8G4pL`&`DF=K2bo<=zn1OWmyV?^RP<(myYO*826a zm7>EEbn3G@IP*n+v_QnR09y&Hc@OMxKX$#(8 z9oHxB}X1|DIf`>Q_W4e%N3k^8&nq@$NdhQSOGia(7*WSWqP>lCZ&yP54bE0IgSc z9+FNq21U$~F-BYcLQ7#6OD44xGOV=*H(?&`0*;q-uovU+9H zYEzszzPM)N{GAcb$s_%Jhf&(TSOGj!Z3pF3N%VD@Jj6UTETvZ%o!)FpT}Aiv`b@`2 z7^(K?Ax28k0PZHyXF)7!EK*Xkcq z!PgQtjKfXLpF8v-SC04lI9e7PAWn#i+_L19=TV7i|5xsBX5O_KoW9M~p#6gx#}^%6 zKjrWbt1Qh&4_#dx^obl_MB{GY&zSQm28mHSa2inxxd30s^romqq_w8)?u*JZD z%dPy_uuYA7m;5SzGbCL$lP4mf2ycZohWSjG%)R;D@8_&FU5S;1} z-y!L3l1W~i_myT3=Pq%$eZuX+UE!|WR->Gs+$~vYc`J3tzTS48TL!xs%-nu>>DfnF zB?C^F^%bAo+wp~XW9PZ+@FZ*heT8=SWhK+WuD*k%VEgL4t)gK z#`qXnWUQ^2ev=pHPdqBAH|OcB12YS!dY?JktbM#~W~!U*hNQ43cDHad}#WN6SFpMYH#455IuWC;^m#= zzws*E&?~P?i%j=jlI0ESr(7ELjZaSB;KCE8X9oAb+&$28`lcn5#$RZ&a!vCac0+!8 zVditeenQUTtP`s3M;TUhJ@bw=woO3uGU zQ{HW8#K)hT%|rv|0eEJ_lwqxRmG5n)H^-Y=%~ol_2$%dlT$C*2kp1& zAGqyQ&iG9<|_W4IVeR(n9QlY>5n!)S5+&x;GTTOl7*2%bgL4nKj>6_=f zrIj{Vef6^^@tMQl^f6j@(Qd%*S6{5U{^RMq1ux}SrZn?@Y7pCJ)Yxb9FBl!1bK9jw zszX-Et9_4$<@~WG)vC4VWZ>9m9Y_6cZ{NH0zW&dtZ5QR%Dc*X~wMXw|T`!Fq-C*jd z0k_OOqU*hyytp6_X?x*(Z{NL}4^P;U9aWsMqPflTlbI(+{Aau{YwUMB zv%ebr<P` z$Zf#x)kQC2HU|W({wUu&)p&G#r$%mOr(}E0*0~+K%)DIZS%Pq zg)y&xJ$K^vijIq?JAYh!=gx2WzL&==Z@+utt;5R_|2R5Q)oc2lw{K5PR;-=2I&IDI zx{VZ3d7E3urzhTe{zcQT#~*Z<`tt4CMMCgPw}#Pnc;U+;iNv zL!ohlF70>Sa?NPgsk6yjo91KgA23}1!>3;cU0(dEr=NM#qVvBOSX?nI8P#ykF(+xT z&gAAB;*PBzw`W6SbNQ1+w+~09FCKa&AbHW)T`jD3t-oU4(JOGShpgRqW_iMSfpY~d zgC1;7j7;7dG`YUP);Ie+UZ)${ExRVXb*{mreH%SK8DV#~?`6vwdxnhFZF}u=Mf}sm zxB&tC<+s|kFwECqZ&DmE#K!(w-=Mh`D^7~%Wj!crW$D)R#E;3ZhK}`cPf;dydNxLA zo$L{^_UN>Q8Q1%GT}hW-&;0C%0WpIHh*vwMbZK-cc*B5{_212Uoa)eh>)Lq@Hd+;% ztW+MEyy|UoRz!+$-iq0OxEvX=CqGC3RmQhz%ZhcqCm*}g;FSN$(IuBx6}0^}$7lQZ z?Y{g@KIzu!MXw!leG=;g&0AE+f}UR6WTGGU`6!qCLDx;zWk&{$47@rZJ}3KOv$~HS zTngFh`NUM38Cj=Jq~Y4DC&u1fmEq8L%Bp+LDf=Eg8?pH4(fb#Fae2IW$c@&Y4l*tN z{=u@TI*tqOjLUu@>Ni5@d*R#FUpJC}|Fl=60>aveFDfXp| z(JxMZU~%j5o|85yqi*K+_lrFj7_{k1!L+bvlEcx#dA%CU%{NcFH(+h?bo z96QkD;Mz&Yzq*(`ylG42=jWC_-uqifbNRHaaEXhkP3e%I`rZDWxwRN=J!)jTymRii zRZj<|$?~6_6K#*Yvd27lN;650{;CIsC;w<3TzpCIn0ef_C9R*`cUv3wU{!vq*Uw8D z&6}L;^0GluTu8y}{_Qs{cAgZkzcRVVduLC{gqwmzI~E*Y^=82jxsBHAn#`GZ(5GR_ z=3iYC3>!sYKW@va_z|B59~@^D`Y?J(dtYT{TAS;#Uwd43 zZL|GH1FK8(QzZ*7S)OlcnZ3RLUCXIibvgC<#vi-t zTt5>rZLh9{NcZ?8$rttg($9G1um5spiA%c!r&o>8Kb+)zDyi3*hw~nudA#{*=H~cC z?*5hwl-mb|<=@vCmRw|$khXf_i(cKu<_}-=+Gyr{*C?vKPv=eE2TH|eD;DK#KT)23YT>>$W@lDQ2a#Z0tH!BX|Pnx%!xF`5$gTzlK=Kja` zD|uSn!evL#nlafxq4;T^ z>5>jtQwqL1D@?xA!`QC3rT3%9#yQpo;yKcTtHSrMSbd^VP}gf+!m`Z`93L#7ly)R) z&!a`IK4zYCFF6J0PMEPsVgI;E=n@aBp&cxJti)Yb#+Y;*{8@UzJin5p9ES~yN8GX4 z@Si?E>@RSC6*o2Gw=Z<2d~bOm&@}NJYyP=cnri!72lKh1wr$J;O1=BUUYez6wf@-Y z8|}Wx9-@2Ff8W0EuA^b?6(?@8qsc?l2+Dap$ML6%wW+}*ygc+U%cA!o^jH8| z{}iXC80*y=lPgiYEG9NwA$PXuB9>T)aAZpn94-%awixa=z{bHs6syE>dub$2zdKue zEQ_`1?P6@yOX?UD8G{q(A~2B0I!c`_!j#HrM_b$2AWT1{v0??ze&Je(A|^_zL@*}Q zHaJE)8H}SMZM#Y&cD7N{aJhvjFtm%aMWnKeg-DqIUvLC`fuUU~t}DgC7aRefG$;rs z{gI-~!^hydI_A$b-T0Vpe46fjOm{w}2OraekFn!p>?}lKk>TC`1wIu8!b+ z7Pc-VJ$l0sb5;xTbMMh0Oiv}C74D5iI?X~)G$@Y5O{)+b9Ah|8R^$MR{iGt=WfEY= z2-bjo&vH=Mm9_qj(yQMbRI#L_B=(9})MtXCrMO_q42o!R$YlhR`b=0PLAXBCEwbX` z4U33@rV}tDE*~Ae(ZfYb-xsuDS-cM7@vbEvH`Xn}DKmBm1(>o^R18z$*MR8?sgb>f zI$YTeiYNnj8I)>-R^#y+QUF-A4fe2sO==hdWq zem;= ztGWZwmT_lT1X&NS@omuZ5ugOXFvp^S1fZfONsF4AQfs6eTJU!R^>2YT^;it}z>P3#OsayrFAmp47b^;G4@Nhy?Dd_|q^dPPrHKH^K zbDLaTygE!>A^JLERtN8i$nh3}9M9w@KNP-SGqG|L@37vP;jyX#J z@(US7dE+M;5)^PP(PhF^5@Y39Ua)P;L?*-_(gORR?Qw?08s}gfapuJZaRE5}u%2bH zT(+AX7n~3@5t)gai&}{~h$Nz}qHZEbk+7|ug^olZ5lRdtbtT4<`jQ5cCX%L-))Ko? z$5NM4*V2BaV@k)Cjw{ts2~>KjIx0g|J(Y>dT-8F=M&+z>RgF~zsK%*oz_R{6XNm5{ zA7{ZfuuRmvnW&}6Kw>1RCoz$jN*YVdB&{T)OZ`g&N_ABRsEd=zUv*P;_k(L-P$xrg z2TNx&lIS}a66ph#P(?mqNO_F>7sc$*?ffFP9jw&K8NZ^T0KRIgB8jsE^SqL=^Hpy zMl)b&cu}YO;qc&63|LOD*>$pv=Y!tKq~>Q1hf*+NR7H~A5^_Ap8!hh{YZe;`?SAFdjwN}ra&@4`#=i-TE8y?X#JiJ z&`#?{psIB|t%E5&QCiy*rF}H@`q-4?iKuERUDG$pv=UIS=TXLI-mak z3$5qr1yTBE7__FRbw52H$0rz>IeZ2`*P4%8B84|D)J0#-mL zfUb82wFYbeF<=YOenc05uD=Dkm-#77(7N|afX>}1uwx^_7ntZPZuH%(4{>HpPlqps z_GR=9$(qz>KR^a>fwCX3$?E@%VTW*1SzH&K29)A_8+{A)uQ(H&zN7NVZi&{02c0?L z|9iqnv_1yk8R`d0-%_G;i6n>GI&+jydtp>Ix!UHV|C>Wj52qNZR66@evZwE4g>ZFJ ze+NnZ^;&h>s(!6dK1rPJ-P)GV6-^s!aC+~w{KM+wP$qw_@wIIKM^tcG`8tfgA{d3Q zI1PgpOr$Fxn3sMK1jng8#(cWyEn*(}w!?|)7{-#Pc5d(ZZqV6NA0cH@-m&$mk*ATJlDsZH@w6*3LS^qk~lY{YPk-70cS@sTMnyyp#H2>t0_F+5RD zVtwPnyne5(Izt^JZ$$StCh`)m%ivB`v_IrZt&Hj)88Q58s0U=oKgm@*7q9adU&4&EEm5LNn zZJ-=PLW9iA@QFM-H!N%CEY+k3O2-K2bZJykc*Uh#x~zoq;R-{IL-|JFEU++Tg0!U1 zC6lK^4?^f+ECAt08DgNa@OVj~M?*HzeCqoch3;txy+}IltS$bE&N-ZMEQptM3Vuf$ z>M4gB6TsI=8R{;zRxKL~sAZ<&EP?kyEmi~9)^MRVsO0N>GOi{Yt`v)j8`mQxSv8Ui zSL>A87NG%gQ4tX_aX}Gb0fAB61TI<2DU=Da^b{SJpiWUJH8nUgZJ+WM6WAxxFUl{r znAZfghEq|%T)Z+xtx8N*CE~oCko^6^!s4O={Uf3R41w{<(5X4CPOVXLa#>0Wr%}q) z8im%78h74KOOH=Umg6p&4pu_4N|wSUt8|=6rhGYR*YfT+&5bYT>QSzzrxVV>pJ%!L zVxs(_Lny0|I6Sn6hf>oQt<#VYL&IYN!(-wC2f}ZhA3Vmy1^C4T!aMv*R7#y&YO-9d zP`dHbcaxJ2)z$UwA-VXh3P9$IIj+6E*5|l_E~APEl*( zk`>Pw&4AE=;J}zNq8Od5NL1>cJK&hu$Wmov2wFEb?OBB*G?Fq>Ewq?tPc>hW$|_H4 z0)@p{YF(kaPdSeh#T(w=FDx`5kZ-|M)5@vR#(q5q3cf_Ys1tMZj}RJ1C>n7bB}Az5<%Gh^ z+z^yM#9LNS6AT$}Z`)Q#U|X)ACYeJIH7Z@H8Ou=z#Wy@orcxMsyYjm#3PMafB_yt2 zR47Ub&TeTkjaKO_k*ifYrApVu-Ce@9qn7^S+GR=lNIN_^B+vjv9Yn&~;F(1_0clrP z6R*tL6)|z#?3n4w2jQJ#Gczj7v*ue$>8T=WWzVLo2s#~yXV_R42mOdNBjGt;vbN~P zKM{2-30h4W{^$uu&p8GBDKJ(QbrsT2{PBbj=byp!Tcl4E#p8mwJTUU6Jc>_7(dLln zlAg_CigkG6a%>dzA$sPH#j&Uz7llAibN9lKE3P++ahT>H0J$c8t|$kjvj}&)K^mkR zXptUglp$&GMcQ^3z6>R}n@U(Hud>Qt%!_IHPmE7fs^rDX-B@$v_QnbsQ7y|`3L*QAS&I!JF6#~E?FRw!!zPsjXpjThrK zmXuJ>1l_VV>YJcz7D-F&J2>Q)q-U&~J{{+OyZj>2-l9-~LLXu*O=CF}NtXJ`F5$bw zL&6;+sw6&r4@ux@DU>aFf5=hEk1?sIE9z-pQ09@{xEQEDU3ir;7#gTEDe7%FANR;^ zg->6ut)O9-_Y92+gc2Gcs-hCPMhTTuQCw4@FbW@>bkdd!!(Cb(m#S7ICnPHs94V?s zadSQ|Gm(8F0z!jAjZ!H_Yn05w$W0RJM|$+%n>=2bH%eV`)xETY1@U9E)>=*_OI30h zb?KlDaRz;XQz!81NTFwlyhx-m7(_f*X-9{LMn(q4Kt+*gRmo{-N*!tag^`$uj`S&{ zPtdlxWJTe9#S%l~nis5uqOwcF6-lviLt&IBi$0f(BG_ULk(b zaegr|e*PhSFt(=RLG*D&NiM5)7q&k+hQUax(BKR@ztG7&oyZsHX=!{Ajq>RyB$OX) zpnMQ_S*eUkQes*pMafZx>mm$H_@}e*j255SPd}L|{(OE_8jU#bC~7r2Xx}svcu~DZ znD?cbY?@nB@w34+i}oTi`Db)Kntcq%_$Q8^H5BC}=Bl`^QawgF@_BTUXy}rOkP?SE zNE!)|maf3B+@Pm$ytYecDY%-7d+4e#6G=LZalLyH3BRgZ7lzTKKXkz`NVN}+10dTV z5NM=dlYTGcIPR$&KX2`fKr1CllY9kP8tasz?j4W%PkOd6H%!vb;C&<-N=7InVYXO! zV}r5c*kZG>#k(r5NGp7v4mBbwG&nRo4%5OkSIN&GO4OQU%mT+@LIV#0!^~J=S8npy zqwXqEC)18Bq)sOZp$ zaC-h2B1D(|;uAfkgdmRXCh&6u;@h&W;jhndPoUWzn(4{R7&fH!@XQQxjz{z(yn&;; z0{HeWjY`euYWtxk9t}z8g&d=FW^-oPsRmPR48&i@s$^<3)6FJhV zpjlW_hmb^>PDm$)lQP2#C@n6RoMcgRe1VqBPudFI9HpR~9>rf69Mfo0#w){os-YAc zzh^7n9~X7UFOW+A|CK>H$p*&cp+PSYFfcLIu=YDD!rst`08X^$X?ZRkG5)-Uc zDK&T($(J$4Z0V^g7rsrUDrG8qkB3%dc>mghsy>YiCve&{r5qC>au=>fx)$vXBc;L! z(9G~!N13S92!WPAT78};H{Lz@c~CAX;T~lTDgMnl^b~XG`O0(1*Fe5jlwN?(T}!F- z+KYK>|5V^NbTSk3<7V11z-#K4derREFBI7y}=-m3|4~G z;7hO%(DKNxU=YXvW55dVGw`Uzm>1{_{JKr$N&eyB`^jnJja9i;8(z~;g%YVqdv}DF8`1WOv<0iA_b_xYaj>g z1$m%OL&oZX`k)2q4B~+bYy_LY=O7Q<0@WSyCkDU!Y zKp2<}=71dVCAa||0%TmcSE@hk@# za0>hY?tr$<@GJ)NL3Iw#e&7sdgJa+txC3;}@!SU40F%tDDsTmz!B{W_Oa=46I&cV_ z1T|YQRtq!%oq-&v!C0^sNU;T}1DFW*fpg#$JpP}E&;OTE{uL>E({g_dF%}y0$*b!O zNa)r@&;RFXgB59i<+VL?k-xekFD7e~@_&|o(6|pY?*E>(@1uUNSencyuTCH)1Y2WmM(rvS}>xyb(^ z8JLtm=^G`LHA8utmiIikRiw=4l~L~9QT9nd2eyM9U_ZD7^q^WB#{5Ab2nNwW2bP0e z@D=z4+y$-MqP~HSKnGq2Gr?ML2%H2}+96C(AIL!pm&EP8d1>6OAiOa%3KcEI_ zU=GLu-+*J_9B>ZAd=lslMu0Ss0oDVTAjUR;eV}JB+7CDgE&*)&V$DGdFc1s^Z-TjC z3)l)?T=#oiUJ%TxpRI*K|C3W&e4a8XuRO{t3v>Jb?`Z!OX&1(Aq9W~~w6-9&18M{2 z^8bfqVAB5!@6hnumit>?<^1h0Iy#6iIyyY{qT^qmw~k`oIwEgWa4+A8YdM7VA4Tgv z1`f`Rq_rPY`+hoD*zHlYKC7a85R7+G$6#&J7_1T#cZJZJCE7Qh0{2uvyHscw!OL6c z(Fg0FXjc$d>e@8gK_pxk(k8559ihDSiMH~KmV#VVJ{Btw5L50 z9{9dXd2vZ`5ADjQI8%$Qqob6(gmrI5du0v#>99ba7AN!XfQ=V)m$U_swiwd=asDBJ z{=MVELZfNnY~c<+YJnwrGsGnBb~7x8#^P~FhDzavO>-J`vcgTCuF4k5Ef&YM=z_vHWG(ZC`fGglJXc>v26^H~gz${?a|NbEvQ2$_EH2+Iu&We<=a|Oy7 z%c4=ps4JkPGT#aJ-QXwiGichEF%ATRU@#ZV0~-LgWHJeG0`wia5(c$T4|L&jm-1&e zCK9M#k6-QKkYwj@5%W4lB0{wo{Ci_eO7u{`(k zq{xtn@W8n6etmlK-@D*fE0w2bJhQ?er!OS@oeD$6BX|*op(vKWNnxPA_*vQ|wMlA^ z|C;{Wq$QY7A%UX)zlNw42;;ww>E~ye>VFfk_sMMjS0x~29@*X&o{^TU*`_z#xJ~>0 zns2hLECDUDS5$HWEjMBId{eYlgH4yLs%NjW_+OR8|Id6iwW-N!GYdAxq9&`1Z$8r> zbr81rT?CeuLnj-oeJzI!OS~T`htk6627jep`#aookzX-fEY&SM7Trwk?G?Dk)K3!H zPzW$}|NnTNW+-1z)FCW6WBXD4PJy4n17L$^l>=x6I)Nb2A0&VbFb%u|O7lnIIwOwL zkoPt4yy5(R_va1S4FrDxTgbBk=np1>Y_I}s0=vO6Fd19|`GC3Q^{KAJNN-MS{K{F2uq*HKdBQD#Y4W3tI;px6n8JhySj(gk8NZos+R-@{!Y(c(0CQ zD<>-tCnj^UVjT1DRgd)!vE;*&^>Sb(g~ta__~XRQ)u*na!zmkPQPnC%IH&{{897_> z>Ezf*?w)=RQYoslQX4CFNm)NCDU0sG78RJt-d5Iikpjwkb9Vhg&0TsNHAWq#?H_~v zh3~J$#o+S^+M#Y^Qd2g}I~=}OY9IJ86yzpq_~`E|8QB?A2nYztGspZq9tp4eR!v5JEt3sf`_iT=oNA1gZ?vK zcWmGzTT^qq=KRWdnvhs9B zM~;2RVG1%h6JQN8!!FrWrMuB@ADK#qEqYW#svqf7buVY%}MrWV#l7HqL82{1X zjh{VW{!1MF4y-t_{OtEvf1Kj=&BeMW-|bx^)@4cM8Z(tg-LgK(AMdiZQSJ{RjlXh9 zxqP7B&)3H^IP~$GbuNY;)b^dw;$-&J54N7?PHk;>viWV7^TR%M8sR%Dc)+!9AGWy? zc%xmbs+Qg*C*H1u=imMT(kKhyZM|=mG5jm-J@go`JQJ6#@3oJ zFzAY7@3iU@5#-zkC!;k9~Yc;YP{5I_<^BMA|E#m z?D^%JIdR9j7kvHmoAo~SsJBuxV?*=rPj!#}blvXZAFofnvtnUG*9Bj%`MUpq;;eFq z?AyBjgI@2yb^TlR-R-^M(Qezm`E|sq4qrL0xVOrG^p+onv>P*~(1Mnqym@8!{BeKo9iaD_^wVE|9UiS- zK5=QzvIEuXs8f%wYnriS+?9Lp*8ebWr}u;hSKn>6yvxVxQQx({JhZm#@~zAA+itUl zPqDMwe!#ue@fx)}T5h}2V?~2D?d<+?Z8+%K7gbgseEog-*|`rp$2iu{KlR5k$+;?z z2G*XwzpG4PF}mTZ^!-bRZC{nrQ1#oKA9trNncL^w(9AhQwl#9zw(^`~>&W;Sy_GHY zIUKc`89&3avHbeFaVeRb<)drbZho?(_v0m1I?caeb>(EOQ9D-meyx9}t3A&;y|F!P zh;{P|@2E3wk4q04`kCrVi$+!QY*yOc85-v5b)lzxhGgN_ZZmVQ=QnZkuYc&9%!hr3 z^bX0=O>T2{kd;ej?}X)hC%(DjqF>~>C9;ca-aZ(l2@P^v+BM6g&Kbq3psbbqrryf- z?y!0J%v!6R@7OKU?HRrJugu($SynR_PW!Xlp8nhOHrhN~@nz2ZJJx+i?>|@T@Zd$U zkIpVW*8IzjQCq%h@%}#5s4GY2JoercHLkLJ=A7e9e*3~&JDc=(26oE}y=eE|`V{$q z`13&-8`s}xQ0?aRGYOl+f3ugZNvT{prONX2hlX5Uyu!QZ_{Bf_X6?9sxBuL|d#|1T zrQ5B!VV9b|9%_H*tLyV8Sag~F)3EjTxq$vw(cgc$^us!;uWtL~HSk$D-Qi8G&q8jB zyNlJ-^Yh29Rqx0eWOFC;y5!2O?O(fQ4ZNHe7^6KIFJF7^*u(k#88mcDdCQG|<%?iT44fyd7 z=HDpRW#E7oM^A?QsJ|VYqs+T|lG~DUZo8vmd;{r5o5k0UfBk1e#ho*i_B*CunAh~~ zHUH&F*B9qyNB%Ic&dkx7-5%7+Pfs{DEwJU&Uz_8F&Bjh)tS3B2kwA-7t%Hv3rDaqcdsnz(Fi zcYjNy>n1iLHs;cw+bUl?F>>Ok))LP8z$odvHDi{Xh|F90{**`ET6}S2aetfLlYI|Q z_BnB5=8Y4#)}3FoE@Mu}V5ix-Eul$y*DNA3^IgZ}EFE#*r-Pg0jr%^U9el4=O|2Q# zZf)N$3fvqPzS;5M(eG^>-(B#={tKgyez;*lbLC^_b&veLJ*Um>Yx!x5?*_O9SdIDX z#6q75m)xUcYr84x%#fyUck7beF)M4|xm8Zc!s_vtz__DJ-0x2p}COjz(} z_x7CM8a5uWUGanMxYtK)`cL!+s+{yU=kGnSaoo1-J4^a@xVtR5U%itZ&-Xj>k#wY$ zcIW3q-u4=JbV&7%M{njQUti|_>5VOeyu4Z~hFUgW_9*XodfsvS>LWh&n3WU%`M_!Y zjxO8y!x!>xd)ntNT^rh<-!9MSuD^V;A=vxqo-1p*bU%1B(bc6!qIS)Lk0++9cAiT3 z!r!@RpGBGjF;$!N8k2mqR`q};zHcj({^3H|RHgs(vZ0oB8mK(Y9*!w>#|TwK|`5?1S&DGJon=qf>XMzBg~x*yv*GHeI%J zaq?#immaDk_q^bdwBFIS%k>4La`vQdzd5HzltcK8GhG#%hQBdK?RBeO;=JC@eOft1 zIlFl*(%7}`_4bluGh-f2-srt*ZvUSotN!D6@Uvqf57Q^C`2Agr@n1Q85pO^4By0Fi zWR8BzU*3*065X3Q3@zyEr#&;ZlJm;_M=rH^cYT=k*MoQL*oSvOhOApyx?)#zX$miH zGcqNpzmdI*2VklJ7WtM!o<{nhsYg?ds>owQsG3iyC`RHp4aro!DGKRSNg?sdj%gUC zm7pk$dsT|3ri>~P*}D?7Ec$;amDo_^{&rP5^XU%diZguJ$5-OvCY5klYJo3bsuF!A z{bGV#y(RPodzC_l?{F%8C1aIZN%w9ws`|*f$Wt_ZWN91%P-(l!d?iUbT^haxt(8Ol zlxf}6ShIm^czKs9)8SN;=&sPnMkCwYG7f?b32k}Va-i?=@1ar}tc%Wnc|L9<#MmyMO6+6AjrZ-ch(>emEw|onx z!5r;!rk$>IFYS1uT`y}}2s;sI1uU(Cpf_RU->@N{VM8Ost-OMd4TKC{7zdhzR-g^Q zM+fq~VPl>upJuNtF%yMahWXSY=)4DO`nx@B;Xjh;+2qNS*+cqXK}}|v{}wLTGuwQm zQ}BpDYBH;QDb8y$>wIV4y-Gd>U}`K`Ro)-H(y4@tbbn9SwGHkTaL4~}!zY5OWB zA!YXLFr|;_@oUShtx%;|cPk4%?ppcefxis9s{|hh0M?iqCS!a~_YsuptAGqf+bqG> zmDxAXV)Uk&-(n6o`p0k-4jBqt-@|ere_}YdMCl-gok+<}w3403=}vryL5Ud$CBCIF z5XE4LBCtdbCZJd+aF9NNqhQl4_!N-Mw=dWYSP$MEA@DX;2)ZscxRV^{Jiu`7WH=8q zoM##AAcK3h;k=jOe1+j0b%jclGE^Dg-&SG0Ag$9IjbCyl!H7nm5t_U@P zI*QOd8) zcSJartWqTlON+`jmX(B(qf#$2lj$%T-#1Lf|Gc69=fYTfH$L`iHrAG8N{!tQ>!p(U z6E*@L`qR4R&!?av{^4 zYCnt>>yCb-Ictd?!UbQT?}G2jcZ1tdHi4~Vxoi{rgdMOvWLb}M;2LsGxK^B$^W@s& z<8fBaJ4r00mQpKe6=^kT4QWkjEonVzeQ8r^r-Cj8-3odX1QZM^7*a5-z(Q}SucWW6 zucEK6x6?c78|jvtFKY!k6R+m3;ieN((0(=Nifu&zwmm!7r;pW%n#GyyikPD0a;r^G4KR z3uX)~LNqH3muMD^%sD`*)$2{AW6fr1Ip(nNlVL?in&%ba7)1j5+GgA1|-=jyiW{ld)Px@(|oJ~HpNe+L!G)PX47Me^XPqU z&*@!T%e;@`4kzs?#Z95srSkWd9a2mPGNSwjC6l0S}b{u3RO%t$U|Q=dXM^)_UijadR_3792dmVj9TW(k-jV3vSc z0%i%AC193-SpqLp0%eW=El(ajxx}rJ{o4yM{&#t_k;eZU0FBi#^u|n{FfJbso5uSo zfX4eYLq~H2;{na4X9AkZmns!quRpaXgKKX?Bfl3Xg1>2@=M~_I#Ld zD%GZIW@DCsSpsGWm?dDAfLQ`&3792dmVj9TW(k-jV3vSc0>U_+#@;lhruXMGj;Ap^ zy_cqU-}IiI#``pWr}yLZUY_2`8~)u6KQ5M%S9CA)yr_*3n*s~Z1 zR>?w?1Jxm$DpZ?1D)FawZ#`T|%0Y&lEkSJsgnDry`NzXfilxXD!1pJ#vJ&PrH^N3qhk{Ydtq zC)U8y8`s&(6*~#qbKmUSx|P=p`b3j^fLhKsXgYSoNqQ=F V4!C)LY*z$9Bx7HLtP+yRDufVOCJV_Vve8;wDX~YXt=8hDs;adV zZ7tPOt<+M~(%MSjYKv4YrDVSUbMG8;XEKQ-RQcYy^ZU=a_uR8S=RD6j=Q+zga=7M& zl^;4>WCmAHX2FUyRhX5`-VFDt{MnANG~AP2kw&8->l6UDrt1Zw!0&7JG9OmOlCi?j z-BgH-p=5DcGv@aOW40`Ic_#g zJw2br!vhD#D9fqZd>NV)-zKErFdV~YqL2LI;mGaEa?kVkxbP|(eo1NI;c+_g`nKu* zCbQb=(~nAw+h44UGDTqA9}jmX=s;Dp7U~^w8Pz|!xVzP;2Xys=J4cxOnZFlbK7~IX zE)R;A7sVsMlGB-+JbwPnP42%Wle;rCd41$&N&dM#kDou6WE#f9pE;fRb4ex-mzSfV z`MCFn?w{5(FRzl)U6MUdZ+Xp1$1ZC;l4WDrLuIq&w#A}do^5S z;5iwls~Cn_^h^J)%nNUH&k=B+!m`DXyE8ZZ+D5r0IA_mN{unfHFjKy*OjoJntTmbN zn}HD3NTtAH5k?yPsl?dm`4uq+0Wqc_v{><-z!G4l!40L0{E|sFQYe`$3HMT}U6C?Z zRz-6$C~cUH=Jf2hm2`I_?27WeJW9dbp#||#L3dOWf}FF>6&26(Xrw{P=ZesAvuA|w zo__r;@0s~(bA`1=pK@)K-IcFRbxSxs+ez6rB75IrB7Gb$u3sJgO}dQfr| z&EwL-ODh(1$P~*mlZ^xwl0}NSvM?6H0<=%wBCTRTKgq3>QcA~>xVM8QEAI`SH*}Wr z@6;8cW(pxRe!iLFR>CHgnc_;~rRljjM4=t36DbZFiP{t!QP-KZWM&GgM^s`|izJ(D z)EX&ulFf|pkz!5AKxvW-b4B1B>u{=ry87bEa*#G&W1eQ-gOC~(V)7HyN%tArl5);g zC9WJ}l|}U+H>ZB+{h>3${W4q*CVOs(p%eb8;w;I-5r{fo5OuZEC0%wHXH zK#Is4nYiaE&t$wDIN!+YkbqPY*Hhh!2jv7kj^laJ_c2D4tODE$sFfu5sMb>$g0>W> zR#AEqV5;#h1@~cap_7r`%#%eUjUFrz<2!-51CDSj)gF@Kv3Tb7QHrZPv2l4S#S?)z zLXiT07KAvZ*g6;qU6RdG+NBVP&k~S>I5BtONUtY&g;G2QkbYDX*2Mi3hVlxvi{*Kk z5iUuO7>2qrz&1Q~L2gd9S7#4BG{-8mbtp;d1GA|N^?&;1Db?x6Q&Wk2g&Uz`aSHO- zDi)77@=rA2<;8Qzuir)_z4aaF92P)vOUcfnDamZi${j>(FNjmcE`sZ!Ea8IIkn z3)KZ&=^4p6F7}Ba;du6m_6iCJ3Vp)lNMtNaa-1`>G7_?qQ&r9_nq{_dX`xOV)uN@) zN@%N4C|Z`9Wj~LwXpiu44==w!(C8@9SSC>Qy|sRE5Go-2P9N)-a`iaIlY* z-Eg0Qs3e9JrA3QU$rc_N{6sZmfWLPipC_%Z+CUzkmNsom%}iLN((4JUYCw>eM?f^M z0#8znf;Ul(-KIqZ#7BX6FC#AkZw6;%0t)?zM9vy<5ia~ngh_Q&|s(8pe2HyYE@58#HH{`7ipF;3Q&xraEeSlCr2jkx#y)zG( zk$CP0`$*b4K_MeU_}L^Y}feig61oUc1RLF^^*sa&Sb2(PN7kpgK{n6h({ zjYiV5=;T{wSS$SG61Wx8?vH%LVf;vXK+-nRc$hRHl(!7jMjCDNywlj7bc2!> za1?ZZG$I#J`_nMGCciqDS+El@nkF~;Vd|&AO_rjHwr+A7DIc{|Vc@N3lxPrmi})-Q zPhNQHFSa4kVyQ*rDHv~Q#3)I9YESw+YG2CM7NWyMBc)_@T!spRzvzUtlz3G}bX;1t zIx9L&9i5#XPoqCa-I&W!@bC?Xm;S-xNGHfw9HhxdVfx)Kbbt&;agWAtj)JETI&9=X zX2*jr#hW06p$AS5^PS=l=m^8A?NCGJIOpbHKX-pVYE#8MT0tO$P=ypotRsX z`~JUhcbjtYHpE_Oye*eb9!l?G62d_8^i+_XaC`ye0q1*emd^k8pCbQ1jngN>P>2 z3-I;{@WE`x^UMAJZX^E!wC|4-L7eZoSsMS-toYOG|M!=z|IqQSG-{`@x^C5nz;xqv z{T83kkCF>o(UOGLKMU(eX#EDwAoqrJARi;}B-c{tuV!e9)>oR}m1b5sEm}bft{d@J zbcD|}TZZFx9;Y<2mvqDQ&qw!9zfT}vaTCpZNf_#@vsBVxznuL5(oyOS9WZ)U3Vf6- z*L?>12V%BYJMHD(f;z|2YjNT@EA!FpF1?cVwMFfKzEy>l1F~tmM*;j1Xa)`>STbx{#}{yR5X5ieFaIs7p=x33b`cUYCk=0)YlBi)q2Jy0UuM#`NJd$ z9@ip2+xMLBxmle5xwen=d++6459+FV60P6!$LsPj#Ph`KPk&tS*!I7ak%0D<-bmoZ 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 diff --git a/doc/精读报告/data/NotesProvider.doc b/doc/精读报告/data/NotesProvider.doc deleted file mode 100644 index 921721eeeeb9a676f124b5c23f98fb362305a524..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52224 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 b75FI3#mNyxFuT_CtqGO2T$kIwO@aRhHt?M5 diff --git a/doc/精读报告/gtask/data/MetaData.doc b/doc/精读报告/gtask/data/MetaData.doc deleted file mode 100644 index f876671..0000000 --- a/doc/精读报告/gtask/data/MetaData.doc +++ /dev/null @@ -1,118 +0,0 @@ -/* - * 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.data; - -import android.database.Cursor; -import android.util.Log; - -import net.micode.notes.tool.GTaskStringUtils; - -import org.json.JSONException; -import org.json.JSONObject; - - -public class MetaData extends Task { - /* - * 功能描述:得到类的简写名称存入字符串TAG中 - * 实现过程:调用getSimpleName ()函数 - */ - private final static String TAG = MetaData.class.getSimpleName(); - private String mRelatedGid = null; - /* - * 功能描述:设置数据,即生成元数据库 - * 实现过程:调用JSONObject库函数put (),Task类中的setNotes ()和setName ()函数 - */ - public void setMeta(String gid, JSONObject metaInfo) { - //对函数块进行注释 - try { - metaIwnfo.put(GTaskStringUtils.META_HEAD_GTASK_ID, gid); - /* - * 将这对键值放入metaInfo这个jsonobject对象中 - */ - } catch (JSONException e) { - Log.e(TAG, "failed to put related gid"); - /* - * 输出错误信息 - */ - } - setNotes(metaInfo.toString()); - setName(GTaskStringUtils.META_NOTE_NAME); - } - /* - * 功能描述:获取相关联的Gid - */ - public String getRelatedGid() { - return mRelatedGid; - } - /* - * 功能描述:判断当前数据是否为空,若为空则返回真即值得保存 - */ - @Override - public boolean isWorthSaving() { - return getNotes() != null; - } - /* - * 功能描述:使用远程json数据对象设置元数据内容 - * 实现过程:调用父类Task中的setContentByRemoteJSON ()函数 - */ - @Override - public void setContentByRemoteJSON(JSONObject js) { - super.setContentByRemoteJSON(js); - if (getNotes() != null) { - try { - JSONObject metaInfo = new JSONObject(getNotes().trim()); - mRelatedGid = metaInfo.getString(GTaskStringUtils.META_HEAD_GTASK_ID); - } catch (JSONException e) { - Log.w(TAG, "failed to get related gid"); - /* - * 输出警告信息 - */ - mRelatedGid = null; - } - } - } - /* - * 功能描述:使用本地json数据对象设置元数据内容,一般不会用到,若用到,则抛出异常 - */ - @Override - public void setContentByLocalJSON(JSONObject js) { - // this function should not be called - throw new IllegalAccessError("MetaData:setContentByLocalJSON should not be called"); - /* - * 传递非法参数异常 - */ - } - /* - * 功能描述:从元数据内容中获取本地json对象,一般不会用到,若用到,则抛出异常 - */ - @Override - public JSONObject getLocalJSONFromContent() { - throw new IllegalAccessError("MetaData:getLocalJSONFromContent should not be called"); - /* - * 传递非法参数异常 - */ - } - - @Override - public int getSyncAction(Cursor c) { - throw new IllegalAccessError("MetaData:getSyncAction should not be called"); - /* - * 传递非法参数异常 - */ - } - -} diff --git a/doc/精读报告/gtask/data/Node.doc b/doc/精读报告/gtask/data/Node.doc deleted file mode 100644 index fabe296..0000000 --- a/doc/精读报告/gtask/data/Node.doc +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.data; - -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_ADD_REMOTE = 1;// 需要在远程云端增加内容 - - 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_LOCAL = 4;// 需要在本地删除内容 - - 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_CONFLICT = 7;// 同步出现冲突 - - public static final int SYNC_ACTION_ERROR = 8;// 同步出现错误 - - private String mGid; - - private String mName; - - private long mLastModified; - //记录最后一次修改时间 - private boolean mDeleted; - //表征是否被删除 - public Node() { - mGid = null; - mName = ""; - mLastModified = 0; - mDeleted = false; - } - - public abstract JSONObject getCreateAction(int actionId); - - public abstract JSONObject getUpdateAction(int actionId); - - public abstract void setContentByRemoteJSON(JSONObject js); - - public abstract void setContentByLocalJSON(JSONObject js); - - public abstract JSONObject getLocalJSONFromContent(); - - public abstract int getSyncAction(Cursor c); - - public void setGid(String gid) { - this.mGid = gid; - } - - public void setName(String name) { - this.mName = name; - } - - public void setLastModified(long lastModified) { - this.mLastModified = lastModified; - } - - public void setDeleted(boolean deleted) { - this.mDeleted = deleted; - } - - public String getGid() { - return this.mGid; - } - - public String getName() { - return this.mName; - } - - public long getLastModified() { - return this.mLastModified; - } - - public boolean getDeleted() { - return this.mDeleted; - } - -} diff --git a/doc/精读报告/gtask/data/SqlData.doc b/doc/精读报告/gtask/data/SqlData.doc deleted file mode 100644 index ff9ab81..0000000 --- a/doc/精读报告/gtask/data/SqlData.doc +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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. - */ -/* - * Description:用于支持小米便签最底层的数据库相关操作,和sqlnote的关系上是子集关系,即data是note的子集(节点)。 - * SqlData其实就是也就是所谓数据中的数据 - */ -package net.micode.notes.gtask.data; - -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.util.Log; - -import net.micode.notes.data.Notes; -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.NotesDatabaseHelper.TABLE; -import net.micode.notes.gtask.exception.ActionFailureException; - -import org.json.JSONException; -import org.json.JSONObject; - - -public class SqlData { - /* - * 功能描述:得到类的简写名称存入字符串TAG中 - * 实现过程:调用getSimpleName ()函数 - */ - private static final String TAG = SqlData.class.getSimpleName(); - - private static final int INVALID_ID = -99999; - /* - * 来自Notes类中定义的DataColumn中的一些常量 - */ - // 集合了interface DataColumns中所有SF常量 - public static final String[] PROJECTION_DATA = new String[] { - DataColumns.ID, DataColumns.MIME_TYPE, DataColumns.CONTENT, DataColumns.DATA1, - DataColumns.DATA3 - }; -/* - * 以下五个变量作为sql表中5列的编号 - */ - public static final int DATA_ID_COLUMN = 0; - - public static final int DATA_MIME_TYPE_COLUMN = 1; - - public static final int DATA_CONTENT_COLUMN = 2; - - public static final int DATA_CONTENT_DATA_1_COLUMN = 3; - - public static final int DATA_CONTENT_DATA_3_COLUMN = 4; - - private ContentResolver mContentResolver; - //判断是否直接用Content生成,是为true,否则为false - private boolean mIsCreate; - - private long mDataId; - - private String mDataMimeType; - - private String mDataContent; - - private long mDataContentData1; - - private String mDataContentData3; - - private ContentValues mDiffDataValues; - /* - * 功能描述:构造函数,用于初始化数据 - * 参数注解:mContentResolver用于获取ContentProvider提供的数据 - * 参数注解: mIsCreate表征当前数据是用哪种方式创建(两种构造函数的参数不同) - */ - public SqlData(Context context) { - mContentResolver = context.getContentResolver(); - mIsCreate = true; - mDataId = INVALID_ID; - mDataMimeType = DataConstants.NOTE; - mDataContent = ""; - mDataContentData1 = 0; - mDataContentData3 = ""; - mDiffDataValues = new ContentValues(); - } - - public SqlData(Context context, Cursor c) { - mContentResolver = context.getContentResolver(); - mIsCreate = false; - loadFromCursor(c); - mDiffDataValues = new ContentValues(); - } - /* - * 功能描述:从光标处加载数据 - * 从当前的光标处将五列的数据加载到该类的对象 - */ - private void loadFromCursor(Cursor c) { - mDataId = c.getLong(DATA_ID_COLUMN); - mDataMimeType = c.getString(DATA_MIME_TYPE_COLUMN); - mDataContent = c.getString(DATA_CONTENT_COLUMN); - mDataContentData1 = c.getLong(DATA_CONTENT_DATA_1_COLUMN); - 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); - } - mDataId = dataId; - - String dataMimeType = js.has(DataColumns.MIME_TYPE) ? js.getString(DataColumns.MIME_TYPE) - : DataConstants.NOTE; - if (mIsCreate || !mDataMimeType.equals(dataMimeType)) { - mDiffDataValues.put(DataColumns.MIME_TYPE, dataMimeType); - } - mDataMimeType = dataMimeType; - - String dataContent = js.has(DataColumns.CONTENT) ? js.getString(DataColumns.CONTENT) : ""; - if (mIsCreate || !mDataContent.equals(dataContent)) { - mDiffDataValues.put(DataColumns.CONTENT, dataContent); - } - mDataContent = dataContent; - - long dataContentData1 = js.has(DataColumns.DATA1) ? js.getLong(DataColumns.DATA1) : 0; - if (mIsCreate || mDataContentData1 != dataContentData1) { - mDiffDataValues.put(DataColumns.DATA1, dataContentData1); - } - mDataContentData1 = dataContentData1; - - String dataContentData3 = js.has(DataColumns.DATA3) ? js.getString(DataColumns.DATA3) : ""; - if (mIsCreate || !mDataContentData3.equals(dataContentData3)) { - mDiffDataValues.put(DataColumns.DATA3, dataContentData3); - } - 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对象。并将相关数据放入其中,并返回。 - } - JSONObject js = new JSONObject(); - js.put(DataColumns.ID, mDataId); - js.put(DataColumns.MIME_TYPE, mDataMimeType); - js.put(DataColumns.CONTENT, mDataContent); - js.put(DataColumns.DATA1, mDataContentData1); - js.put(DataColumns.DATA3, mDataContentData3); - return js; - } - /* - * 功能描述:commit函数用于把当前造作所做的修改保存到数据库 - */ - public void commit(long noteId, boolean validateVersion, long version) { - - if (mIsCreate) { - if (mDataId == INVALID_ID && mDiffDataValues.containsKey(DataColumns.ID)) { - mDiffDataValues.remove(DataColumns.ID); - } - - mDiffDataValues.put(DataColumns.NOTE_ID, noteId); - Uri uri = mContentResolver.insert(Notes.CONTENT_DATA_URI, mDiffDataValues); - try { - mDataId = Long.valueOf(uri.getPathSegments().get(1)); - } catch (NumberFormatException e) { - Log.e(TAG, "Get note id error :" + e.toString()); - throw new ActionFailureException("create note failed"); - } - } else { - if (mDiffDataValues.size() > 0) { - int result = 0; - if (!validateVersion) { - result = mContentResolver.update(ContentUris.withAppendedId( - Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, null, null); - } else { - result = mContentResolver.update(ContentUris.withAppendedId( - Notes.CONTENT_DATA_URI, mDataId), mDiffDataValues, - " ? in (SELECT " + NoteColumns.ID + " FROM " + TABLE.NOTE - + " WHERE " + NoteColumns.VERSION + "=?)", new String[] { - String.valueOf(noteId), String.valueOf(version) - }); - } - if (result == 0) { - Log.w(TAG, "there is no update. maybe user updates note when syncing"); - } - } - } - - mDiffDataValues.clear(); - mIsCreate = false; - } - /* - * 功能描述:获取当前id - */ - public long getId() { - return mDataId; - } -} diff --git a/doc/精读报告/gtask/data/SqlNote.doc b/doc/精读报告/gtask/data/SqlNote.doc deleted file mode 100644 index 6e3e842..0000000 --- a/doc/精读报告/gtask/data/SqlNote.doc +++ /dev/null @@ -1,566 +0,0 @@ -/* - * 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.data; - -import android.appwidget.AppWidgetManager; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.util.Log; - -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.exception.ActionFailureException; -import net.micode.notes.tool.GTaskStringUtils; -import net.micode.notes.tool.ResourceParser; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; - - -public class SqlNote { - /* - * 功能描述:得到类的简写名称存入字符串TAG中 - * 实现过程:调用getSimpleName ()函数 - */ - 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, - NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE, - NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE, NoteColumns.SYNC_ID, - NoteColumns.LOCAL_MODIFIED, NoteColumns.ORIGIN_PARENT_ID, NoteColumns.GTASK_ID, - NoteColumns.VERSION - }; - - public static final int ID_COLUMN = 0; - - public static final int ALERTED_DATE_COLUMN = 1; - - public static final int BG_COLOR_ID_COLUMN = 2; - - public static final int CREATED_DATE_COLUMN = 3; - - public static final int HAS_ATTACHMENT_COLUMN = 4; - - public static final int MODIFIED_DATE_COLUMN = 5; - - public static final int NOTES_COUNT_COLUMN = 6; - - public static final int PARENT_ID_COLUMN = 7; - - public static final int SNIPPET_COLUMN = 8; - - public static final int TYPE_COLUMN = 9; - - public static final int WIDGET_ID_COLUMN = 10; - - public static final int WIDGET_TYPE_COLUMN = 11; - - public static final int SYNC_ID_COLUMN = 12; - - public static final int LOCAL_MODIFIED_COLUMN = 13; - - public static final int ORIGIN_PARENT_ID_COLUMN = 14; - - public static final int GTASK_ID_COLUMN = 15; - - public static final int VERSION_COLUMN = 16; - //一下定义了17个内部的变量,其中12个可以由content中获得,5个需要初始化为0或者new - private Context mContext; - - private ContentResolver mContentResolver; - - private boolean mIsCreate; - - private long mId; - - private long mAlertDate; - - private int mBgColorId; - - private long mCreatedDate; - - private int mHasAttachment; - - private long mModifiedDate; - - private long mParentId; - - private String mSnippet; - - private int mType; - - private int mWidgetId; - - private int mWidgetType; - - private long mOriginParent; - - private long mVersion; - - private ContentValues mDiffNoteValues; - - private ArrayList mDataList; - - - /* - * 功能描述:构造函数 - * 参数注解: mIsCreate用于标示构造方式 - */ - //构造函数只有context,对所有的变量进行初始化 - public SqlNote(Context context) { - mContext = context; - mContentResolver = context.getContentResolver(); - mIsCreate = true; - mId = INVALID_ID; - mAlertDate = 0; - mBgColorId = ResourceParser.getDefaultBgId(context); - mCreatedDate = System.currentTimeMillis();//调用系统函数获得创建时间 - mHasAttachment = 0; - mModifiedDate = System.currentTimeMillis();//最后一次修改时间初始化为创建时间 - mParentId = 0; - mSnippet = ""; - mType = Notes.TYPE_NOTE; - mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; - mWidgetType = Notes.TYPE_WIDGET_INVALIDE; - mOriginParent = 0; - mVersion = 0; - mDiffNoteValues = new ContentValues(); - mDataList = new ArrayList(); - } - /* - * 功能描述:构造函数 - * 参数注解: mIsCreate用于标示构造方式 - */ - //构造函数有context和一个数据库的cursor,多数变量通过cursor指向的一条记录直接进行初始化 - public SqlNote(Context context, Cursor c) { - mContext = context; - mContentResolver = context.getContentResolver(); - mIsCreate = false; - loadFromCursor(c); - mDataList = new ArrayList(); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); - mDiffNoteValues = new ContentValues(); - } - /* - * 功能描述:构造函数 - * 参数注解: mIsCreate用于标示构造方式 - */ - public SqlNote(Context context, long id) { - mContext = context; - mContentResolver = context.getContentResolver(); - mIsCreate = false; - loadFromCursor(id); - mDataList = new ArrayList(); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); - mDiffNoteValues = new ContentValues(); - - } -/* - * 功能描述:通过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);//通过id获得对应的ContentResolver中的cursor - if (c != null) { - c.moveToNext(); - loadFromCursor(c);//然后加载数据进行初始化,这样函数 - - //SqlNote(Context context, long id)与SqlNote(Context context, long id)的实现方式基本相同 - } else { - Log.w(TAG, "loadFromCursor: cursor = null"); - } - } finally { - if (c != null) - c.close(); - } - } - /* - * 功能描述:通过游标从光标处加载数据 - */ - - private void loadFromCursor(Cursor c) { - //直接从一条记录中的获得以下变量的初始值 - mId = c.getLong(ID_COLUMN); - mAlertDate = c.getLong(ALERTED_DATE_COLUMN); - mBgColorId = c.getInt(BG_COLOR_ID_COLUMN); - mCreatedDate = c.getLong(CREATED_DATE_COLUMN); - mHasAttachment = c.getInt(HAS_ATTACHMENT_COLUMN); - mModifiedDate = c.getLong(MODIFIED_DATE_COLUMN); - mParentId = c.getLong(PARENT_ID_COLUMN); - mSnippet = c.getString(SNIPPET_COLUMN); - mType = c.getInt(TYPE_COLUMN); - mWidgetId = c.getInt(WIDGET_ID_COLUMN); - mWidgetType = c.getInt(WIDGET_TYPE_COLUMN); - mVersion = c.getLong(VERSION_COLUMN); - } - /* - * 功能描述:通过content机制获取共享数据并加载到数据库当前游标处 - */ - private void loadDataContent() { - Cursor c = null; - mDataList.clear(); - try { - c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, - "(note_id=?)", new String[] { - String.valueOf(mId) - }, null); - if (c != null) { - if (c.getCount() == 0) { - Log.w(TAG, "it seems that the note has not data"); - return; - } - while (c.moveToNext()) { - SqlData data = new SqlData(mContext, c); - mDataList.add(data); - } - } else { - Log.w(TAG, "loadDataContent: cursor = null"); - } - } finally { - if (c != null) - c.close(); - } - } - /* - * 功能描述:设置通过content机制用于共享的数据信息 - - */ - public boolean setContent(JSONObject js) { - try { - JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { - Log.w(TAG, "cannot set system folder"); - } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { - // for folder we can only update the snnipet and type - String snippet = note.has(NoteColumns.SNIPPET) ? note - .getString(NoteColumns.SNIPPET) : ""; - if (mIsCreate || !mSnippet.equals(snippet)) { - mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); - } - mSnippet = snippet; - - int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) - : Notes.TYPE_NOTE; - if (mIsCreate || mType != type) { - mDiffNoteValues.put(NoteColumns.TYPE, type); - } - mType = type; - } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) { - JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); - long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID; - if (mIsCreate || mId != id) { - mDiffNoteValues.put(NoteColumns.ID, id); - } - mId = id; - - long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note - .getLong(NoteColumns.ALERTED_DATE) : 0; - if (mIsCreate || mAlertDate != alertDate) { - mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate); - } - mAlertDate = alertDate; - - int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note - .getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext); - if (mIsCreate || mBgColorId != bgColorId) { - mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId); - } - mBgColorId = bgColorId; - - long createDate = note.has(NoteColumns.CREATED_DATE) ? note - .getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis(); - if (mIsCreate || mCreatedDate != createDate) { - mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate); - } - mCreatedDate = createDate; - - int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note - .getInt(NoteColumns.HAS_ATTACHMENT) : 0; - if (mIsCreate || mHasAttachment != hasAttachment) { - mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment); - } - mHasAttachment = hasAttachment; - - long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note - .getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis(); - if (mIsCreate || mModifiedDate != modifiedDate) { - mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate); - } - mModifiedDate = modifiedDate; - - long parentId = note.has(NoteColumns.PARENT_ID) ? note - .getLong(NoteColumns.PARENT_ID) : 0; - if (mIsCreate || mParentId != parentId) { - mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId); - } - mParentId = parentId; - - String snippet = note.has(NoteColumns.SNIPPET) ? note - .getString(NoteColumns.SNIPPET) : ""; - if (mIsCreate || !mSnippet.equals(snippet)) { - mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); - } - mSnippet = snippet; - - int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) - : Notes.TYPE_NOTE; - if (mIsCreate || mType != type) { - mDiffNoteValues.put(NoteColumns.TYPE, type); - } - mType = type; - - int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) - : AppWidgetManager.INVALID_APPWIDGET_ID; - if (mIsCreate || mWidgetId != widgetId) { - mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId); - } - mWidgetId = widgetId; - - int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note - .getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE; - if (mIsCreate || mWidgetType != widgetType) { - mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType); - } - mWidgetType = widgetType; - - long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note - .getLong(NoteColumns.ORIGIN_PARENT_ID) : 0; - if (mIsCreate || mOriginParent != originParent) { - mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent); - } - mOriginParent = originParent; - - for (int i = 0; i < dataArray.length(); i++) { - JSONObject data = dataArray.getJSONObject(i); - SqlData sqlData = null; - if (data.has(DataColumns.ID)) { - long dataId = data.getLong(DataColumns.ID); - for (SqlData temp : mDataList) { - if (dataId == temp.getId()) { - sqlData = temp; - } - } - } - - if (sqlData == null) { - sqlData = new SqlData(mContext); - mDataList.add(sqlData); - } - - sqlData.setContent(data); - } - } - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - return false; - } - return true; - } - /* - * 功能描述:获取content机制提供的数据并加载到note中 - */ - public JSONObject getContent() { - try { - JSONObject js = new JSONObject(); - - if (mIsCreate) { - Log.e(TAG, "it seems that we haven't created this in database yet"); - return null; - } - - JSONObject note = new JSONObject(); - if (mType == Notes.TYPE_NOTE) { - //类型为note时 - note.put(NoteColumns.ID, mId); - note.put(NoteColumns.ALERTED_DATE, mAlertDate); - note.put(NoteColumns.BG_COLOR_ID, mBgColorId); - note.put(NoteColumns.CREATED_DATE, mCreatedDate); - note.put(NoteColumns.HAS_ATTACHMENT, mHasAttachment); - note.put(NoteColumns.MODIFIED_DATE, mModifiedDate); - note.put(NoteColumns.PARENT_ID, mParentId); - note.put(NoteColumns.SNIPPET, mSnippet); - note.put(NoteColumns.TYPE, mType); - note.put(NoteColumns.WIDGET_ID, mWidgetId); - note.put(NoteColumns.WIDGET_TYPE, mWidgetType); - note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent); - js.put(GTaskStringUtils.META_HEAD_NOTE, note); - - JSONArray dataArray = new JSONArray(); - for (SqlData sqlData : mDataList) { - JSONObject data = sqlData.getContent(); - if (data != null) { - dataArray.put(data); - } - } - js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); - } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { - note.put(NoteColumns.ID, mId); - note.put(NoteColumns.TYPE, mType); - note.put(NoteColumns.SNIPPET, mSnippet); - js.put(GTaskStringUtils.META_HEAD_NOTE, note); - } - - return js; - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - } - return null; - } -/* - * 功能描述:给当前id设置父id - */ - public void setParentId(long id) { - mParentId = id; - mDiffNoteValues.put(NoteColumns.PARENT_ID, id); - } - - /* - * 功能描述:给当前id设置Gtaskid - */ - public void setGtaskId(String gid) { - mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); - } - - /* - * 功能描述:给当前id设置同步id - - */ - 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; - } - - /* - * 功能描述:获得当前id的父id - */ - 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)) { - mDiffNoteValues.remove(NoteColumns.ID); - } - - Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues); - try { - mId = Long.valueOf(uri.getPathSegments().get(1)); - } catch (NumberFormatException e) { - Log.e(TAG, "Get note id error :" + e.toString()); - throw new ActionFailureException("create note failed"); - } - if (mId == 0) { - throw new IllegalStateException("Create thread id failed"); - } - - if (mType == Notes.TYPE_NOTE) { - for (SqlData sqlData : mDataList) { - //直接使用sqldata中的实现 - sqlData.commit(mId, false, -1); - } - } - } else { - if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) { - Log.e(TAG, "No such note"); - throw new IllegalStateException("Try to update note with invalid id"); - } - if (mDiffNoteValues.size() > 0) { - mVersion ++; - int result = 0; - if (!validateVersion) { - //构造字符串 - result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" - + NoteColumns.ID + "=?)", new String[] { - String.valueOf(mId) - }); - } else { - result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" - + NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)", - new String[] { - String.valueOf(mId), String.valueOf(mVersion) - }); - } - if (result == 0) { - Log.w(TAG, "there is no update. maybe user updates note when syncing"); - } - } - - if (mType == Notes.TYPE_NOTE) { - for (SqlData sqlData : mDataList) { - sqlData.commit(mId, validateVersion, mVersion); - } - } - } - - // refresh local info - loadFromCursor(mId); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); - - mDiffNoteValues.clear(); - mIsCreate = false; - } -} diff --git a/doc/精读报告/gtask/data/Task.doc b/doc/精读报告/gtask/data/Task.doc deleted file mode 100644 index 72068a0..0000000 --- a/doc/精读报告/gtask/data/Task.doc +++ /dev/null @@ -1,351 +0,0 @@ -/* - * 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.data; - -import android.database.Cursor; -import android.text.TextUtils; -import android.util.Log; - -import net.micode.notes.data.Notes; -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.gtask.exception.ActionFailureException; -import net.micode.notes.tool.GTaskStringUtils; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - - -public class Task extends Node { - private static final String TAG = Task.class.getSimpleName(); - - private boolean mCompleted;//是否完成 - - private String mNotes; - - private JSONObject mMetaInfo;//将在实例中存储数据的类型 - - private Task mPriorSibling;//对应的优先兄弟Task的指针(待完善) - - private TaskList mParent;//所在的任务列表的指针 - - public Task() { - super(); - mCompleted = false; - mNotes = null; - mPriorSibling = null;//TaskList中当前Task前面的Task的指针 - mParent = null;//当前Task所在的TaskList - mMetaInfo = null; - } - - public JSONObject getCreateAction(int actionId) { - JSONObject js = new JSONObject(); - - try { - // action_type - js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, - GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); - - // action_id - js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - - // index - js.put(GTaskStringUtils.GTASK_JSON_INDEX, mParent.getChildTaskIndex(this)); - - // entity_delta - JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); - entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, - GTaskStringUtils.GTASK_JSON_TYPE_TASK); - if (getNotes() != null) { - entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); - } - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); - - // parent_id - js.put(GTaskStringUtils.GTASK_JSON_PARENT_ID, mParent.getGid()); - - // dest_parent_type - js.put(GTaskStringUtils.GTASK_JSON_DEST_PARENT_TYPE, - GTaskStringUtils.GTASK_JSON_TYPE_GROUP); - - // list_id - js.put(GTaskStringUtils.GTASK_JSON_LIST_ID, mParent.getGid()); - - // prior_sibling_id - if (mPriorSibling != null) { - js.put(GTaskStringUtils.GTASK_JSON_PRIOR_SIBLING_ID, mPriorSibling.getGid()); - } - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to generate task-create jsonobject"); - } - - return js; - } - - public JSONObject getUpdateAction(int actionId) { - JSONObject js = new JSONObject(); - - try { - // action_type - js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, - GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - - // action_id - js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - - // id - js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - - // entity_delta - JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - if (getNotes() != null) { - entity.put(GTaskStringUtils.GTASK_JSON_NOTES, getNotes()); - } - entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to generate task-update jsonobject"); - } - - return js; - } - - public void setContentByRemoteJSON(JSONObject js) { - if (js != null) { - try { - // id - if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { - setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); - } - - // last_modified - if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { - setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); - } - - // name - if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { - setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); - } - - // notes - if (js.has(GTaskStringUtils.GTASK_JSON_NOTES)) { - setNotes(js.getString(GTaskStringUtils.GTASK_JSON_NOTES)); - } - - // deleted - if (js.has(GTaskStringUtils.GTASK_JSON_DELETED)) { - setDeleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_DELETED)); - } - - // completed - if (js.has(GTaskStringUtils.GTASK_JSON_COMPLETED)) { - setCompleted(js.getBoolean(GTaskStringUtils.GTASK_JSON_COMPLETED)); - } - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to get task content from jsonobject"); - } - } - } - - public void setContentByLocalJSON(JSONObject js) { - if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE) - || !js.has(GTaskStringUtils.META_HEAD_DATA)) { - Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); - } - - try { - JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); - - if (note.getInt(NoteColumns.TYPE) != Notes.TYPE_NOTE) { - Log.e(TAG, "invalid type"); - return; - } - - for (int i = 0; i < dataArray.length(); i++) { - JSONObject data = dataArray.getJSONObject(i); - if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) { - setName(data.getString(DataColumns.CONTENT)); - break; - } - } - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - } - } - - public JSONObject getLocalJSONFromContent() { - String name = getName(); - try { - if (mMetaInfo == null) { - // new task created from web - if (name == null) { - Log.w(TAG, "the note seems to be an empty one"); - return null; - } - - JSONObject js = new JSONObject(); - JSONObject note = new JSONObject(); - JSONArray dataArray = new JSONArray(); - JSONObject data = new JSONObject(); - data.put(DataColumns.CONTENT, name); - dataArray.put(data); - js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); - note.put(NoteColumns.TYPE, Notes.TYPE_NOTE); - js.put(GTaskStringUtils.META_HEAD_NOTE, note); - return js; - } else { - // synced task - JSONObject note = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - JSONArray dataArray = mMetaInfo.getJSONArray(GTaskStringUtils.META_HEAD_DATA); - - for (int i = 0; i < dataArray.length(); i++) { - JSONObject data = dataArray.getJSONObject(i); - if (TextUtils.equals(data.getString(DataColumns.MIME_TYPE), DataConstants.NOTE)) { - data.put(DataColumns.CONTENT, getName()); - break; - } - } - - note.put(NoteColumns.TYPE, Notes.TYPE_NOTE); - return mMetaInfo; - } - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - return null; - } - } - - public void setMetaInfo(MetaData metaData) { - if (metaData != null && metaData.getNotes() != null) { - try { - mMetaInfo = new JSONObject(metaData.getNotes()); - } catch (JSONException e) { - Log.w(TAG, e.toString()); - mMetaInfo = null; - } - } - } - - public int getSyncAction(Cursor c) { - try { - JSONObject noteInfo = null; - if (mMetaInfo != null && mMetaInfo.has(GTaskStringUtils.META_HEAD_NOTE)) { - noteInfo = mMetaInfo.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - } - - if (noteInfo == null) { - Log.w(TAG, "it seems that note meta has been deleted"); - return SYNC_ACTION_UPDATE_REMOTE; - } - - if (!noteInfo.has(NoteColumns.ID)) { - Log.w(TAG, "remote note id seems to be deleted"); - return SYNC_ACTION_UPDATE_LOCAL; - } - - // validate the note id now - if (c.getLong(SqlNote.ID_COLUMN) != noteInfo.getLong(NoteColumns.ID)) { - Log.w(TAG, "note id doesn't match"); - return SYNC_ACTION_UPDATE_LOCAL; - } - - if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { - // there is no local update - if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // no update both side - return SYNC_ACTION_NONE; - } else { - // apply remote to local - return SYNC_ACTION_UPDATE_LOCAL; - } - } else { - // validate gtask id - if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { - Log.e(TAG, "gtask id doesn't match"); - return SYNC_ACTION_ERROR; - } - if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // local modification only - return SYNC_ACTION_UPDATE_REMOTE; - } else { - return SYNC_ACTION_UPDATE_CONFLICT; - } - } - } catch (Exception e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - } - - return SYNC_ACTION_ERROR; - } - - public boolean isWorthSaving() { - return mMetaInfo != null || (getName() != null && getName().trim().length() > 0) - || (getNotes() != null && getNotes().trim().length() > 0); - } - - public void setCompleted(boolean completed) { - this.mCompleted = completed; - } - - public void setNotes(String notes) { - this.mNotes = notes; - } - - public void setPriorSibling(Task priorSibling) { - this.mPriorSibling = priorSibling; - } - - public void setParent(TaskList parent) { - this.mParent = parent; - } - - public boolean getCompleted() { - return this.mCompleted; - } - - public String getNotes() { - return this.mNotes; - } - - public Task getPriorSibling() { - return this.mPriorSibling; - } - - public TaskList getParent() { - return this.mParent; - } - -} diff --git a/doc/精读报告/gtask/data/TaskList.doc b/doc/精读报告/gtask/data/TaskList.doc deleted file mode 100644 index 37dad1c..0000000 --- a/doc/精读报告/gtask/data/TaskList.doc +++ /dev/null @@ -1,401 +0,0 @@ -/* - * 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.data; - -import android.database.Cursor; -import android.util.Log; - -import net.micode.notes.data.Notes; -import net.micode.notes.data.Notes.NoteColumns; -import net.micode.notes.gtask.exception.ActionFailureException; -import net.micode.notes.tool.GTaskStringUtils; - -import org.json.JSONException; -import org.json.JSONObject; - -import java.util.ArrayList; - - -public class TaskList extends Node { - private static final String TAG = TaskList.class.getSimpleName();//tag标记 - - private int mIndex;//当前TaskList的指针 - - private ArrayList mChildren;//类中主要的保存数据的单元,用来实现一个以Task为元素的ArrayList - - public TaskList() { - super(); - mChildren = new ArrayList(); - mIndex = 1; - } - /* (non-Javadoc) - * @see net.micode.notes.gtask.data.Node#getCreateAction(int) - * 生成并返回一个包含了一定数据的JSONObject实体 - */ - public JSONObject getCreateAction(int actionId) { - JSONObject js = new JSONObject(); - - try { - // action_type - js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, - GTaskStringUtils.GTASK_JSON_ACTION_TYPE_CREATE); - - // action_id - js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - - // index - js.put(GTaskStringUtils.GTASK_JSON_INDEX, mIndex); - - // entity_delta - JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - entity.put(GTaskStringUtils.GTASK_JSON_CREATOR_ID, "null"); - entity.put(GTaskStringUtils.GTASK_JSON_ENTITY_TYPE, - GTaskStringUtils.GTASK_JSON_TYPE_GROUP); - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to generate tasklist-create jsonobject"); - } - - return js; - } - - - /* (non-Javadoc) - * @see net.micode.notes.gtask.data.Node#getUpdateAction(int) - * 生成并返回一个包含了一定数据的JSONObject实体 - */ - public JSONObject getUpdateAction(int actionId) { - JSONObject js = new JSONObject(); - - try { - // action_type - js.put(GTaskStringUtils.GTASK_JSON_ACTION_TYPE, - GTaskStringUtils.GTASK_JSON_ACTION_TYPE_UPDATE); - - // action_id - js.put(GTaskStringUtils.GTASK_JSON_ACTION_ID, actionId); - - // id - js.put(GTaskStringUtils.GTASK_JSON_ID, getGid()); - - // entity_delta - JSONObject entity = new JSONObject(); - entity.put(GTaskStringUtils.GTASK_JSON_NAME, getName()); - entity.put(GTaskStringUtils.GTASK_JSON_DELETED, getDeleted()); - js.put(GTaskStringUtils.GTASK_JSON_ENTITY_DELTA, entity); - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to generate tasklist-update jsonobject"); - } - - return js; - } - - public void setContentByRemoteJSON(JSONObject js) { - if (js != null) { - try { - // id - if (js.has(GTaskStringUtils.GTASK_JSON_ID)) { - setGid(js.getString(GTaskStringUtils.GTASK_JSON_ID)); - } - - // last_modified - if (js.has(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)) { - setLastModified(js.getLong(GTaskStringUtils.GTASK_JSON_LAST_MODIFIED)); - } - - // name - if (js.has(GTaskStringUtils.GTASK_JSON_NAME)) { - setName(js.getString(GTaskStringUtils.GTASK_JSON_NAME)); - } - - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("fail to get tasklist content from jsonobject"); - } - } - } - - public void setContentByLocalJSON(JSONObject js) { - if (js == null || !js.has(GTaskStringUtils.META_HEAD_NOTE)) { - Log.w(TAG, "setContentByLocalJSON: nothing is avaiable"); - } - - try { - JSONObject folder = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - - if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { - String name = folder.getString(NoteColumns.SNIPPET); - setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + name); - } else if (folder.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { - if (folder.getLong(NoteColumns.ID) == Notes.ID_ROOT_FOLDER) - setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT); - else if (folder.getLong(NoteColumns.ID) == Notes.ID_CALL_RECORD_FOLDER) - setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_CALL_NOTE); - else - Log.e(TAG, "invalid system folder"); - } else { - Log.e(TAG, "error type"); - } - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - } - } - - public JSONObject getLocalJSONFromContent() { - try { - JSONObject js = new JSONObject(); - JSONObject folder = new JSONObject(); - - String folderName = getName(); - if (getName().startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX)) - folderName = folderName.substring(GTaskStringUtils.MIUI_FOLDER_PREFFIX.length(), - folderName.length()); - folder.put(NoteColumns.SNIPPET, folderName); - if (folderName.equals(GTaskStringUtils.FOLDER_DEFAULT) - || folderName.equals(GTaskStringUtils.FOLDER_CALL_NOTE)) - folder.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM); - else - folder.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); - - js.put(GTaskStringUtils.META_HEAD_NOTE, folder); - - return js; - } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - return null; - } - } - - public int getSyncAction(Cursor c) { - try { - if (c.getInt(SqlNote.LOCAL_MODIFIED_COLUMN) == 0) { - // there is no local update - if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // no update both side - return SYNC_ACTION_NONE; - } else { - // apply remote to local - return SYNC_ACTION_UPDATE_LOCAL; - } - } else { - // validate gtask id - if (!c.getString(SqlNote.GTASK_ID_COLUMN).equals(getGid())) { - Log.e(TAG, "gtask id doesn't match"); - return SYNC_ACTION_ERROR; - } - if (c.getLong(SqlNote.SYNC_ID_COLUMN) == getLastModified()) { - // local modification only - return SYNC_ACTION_UPDATE_REMOTE; - } else { - // for folder conflicts, just apply local modification - return SYNC_ACTION_UPDATE_REMOTE; - } - } - } catch (Exception e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - } - - return SYNC_ACTION_ERROR; - } - /* - * 功能:获得TaskList的大小,即mChildren的大小 - */ - public int getChildTaskCount() { - return mChildren.size(); - } - /** - * @param task - * @return 返回值为是否成功添加任务。 - * 功能:在当前任务表末尾添加新的任务。 - */ - public boolean addChildTask(Task task) { - boolean ret = false; - if (task != null && !mChildren.contains(task)) { - ret = mChildren.add(task); - if (ret) { - // need to set prior sibling and parent - task.setPriorSibling(mChildren.isEmpty() ? null : mChildren - .get(mChildren.size() - 1)); - task.setParent(this); - //注意:每一次ArrayList的变化都要紧跟相关Task中PriorSibling的更改 - //,接下来几个函数都有相关操作 - - } - } - return ret; - } - /** - * @param task - * @param index - * @return - * 功能:在当前任务表的指定位置添加新的任务。 - */ - public boolean addChildTask(Task task, int index) { - if (index < 0 || index > mChildren.size()) { - Log.e(TAG, "add child task: invalid index"); - return false; - } - - int pos = mChildren.indexOf(task); - if (task != null && pos == -1) { - mChildren.add(index, task); - - // update the task list - Task preTask = null; - Task afterTask = null; - if (index != 0) - preTask = mChildren.get(index - 1); - if (index != mChildren.size() - 1) - afterTask = mChildren.get(index + 1); - - task.setPriorSibling(preTask); - if (afterTask != null) - afterTask.setPriorSibling(task); - } - - return true; - } - /** - * @param task - * @return 返回删除是否成功 - * 功能:删除TaskList中的一个Task - */ - /** - * @param task - * @param index - * @return - * 功能:将当前TaskList中含有的某个Task移到index位置 - */ - public boolean removeChildTask(Task task) { - boolean ret = false; - int index = mChildren.indexOf(task); - if (index != -1) { - ret = mChildren.remove(task); - - if (ret) { - // reset prior sibling and parent - task.setPriorSibling(null); - task.setParent(null); - - // update the task list - if (index != mChildren.size()) { - mChildren.get(index).setPriorSibling( - index == 0 ? null : mChildren.get(index - 1)); - } - } - } - return ret; - } - /** - * @param gid - * @return返回寻找结果 - * 功能:按gid寻找Task - */ - public boolean moveChildTask(Task task, int index) { - - if (index < 0 || index >= mChildren.size()) { - Log.e(TAG, "move child task: invalid index"); - return false; - } - - int pos = mChildren.indexOf(task); - if (pos == -1) { - Log.e(TAG, "move child task: the task should in the list"); - return false; - } - - if (pos == index) - return true; - return (removeChildTask(task) && addChildTask(task, index)); - //利用已实现好的功能完成当下功能; - } - - - /** - * @param task - * @return - * 功能:返回指定Task的index - */ - public Task findChildTaskByGid(String gid) { - for (int i = 0; i < mChildren.size(); i++) { - Task t = mChildren.get(i); - if (t.getGid().equals(gid)) { - return t; - } - } - return null; - } - - - /** - * @param index - * @return - * 功能:返回指定index的Task - */ - public int getChildTaskIndex(Task task) { - return mChildren.indexOf(task); - } - - public Task getChildTaskByIndex(int index) { - if (index < 0 || index >= mChildren.size()) { - Log.e(TAG, "getTaskByIndex: invalid index"); - return null; - } - return mChildren.get(index); - } - - - /** - * @param gid - * @return - * 功能:返回指定gid的Task - */ - public Task getChilTaskByGid(String gid) { - for (Task task : mChildren) {//一种常见的ArrayList的遍历方法(四种,见精读笔记) - - if (task.getGid().equals(gid)) - return task; - } - return null; - } - - - - public ArrayList getChildTaskList() { - return this.mChildren; - } - - public void setIndex(int index) { - this.mIndex = index; - } - - public int getIndex() { - return this.mIndex; - } -} From 252d72e6ec40d03bfb94c169f2f32b57e0c0b997 Mon Sep 17 00:00:00 2001 From: pj36foInf <445038096@qq.com> Date: Fri, 14 Apr 2023 15:50:26 +0800 Subject: [PATCH 2/8] 414 --- doc/精读报告/tool/BackupUtils.doc | 345 +++++ doc/精读报告/tool/DataUtils.doc | 306 +++++ doc/精读报告/tool/GTaskStringUtils.doc | 115 ++ doc/精读报告/tool/ResourceParser.doc | 214 +++ doc/精读报告/ui/NotesListActivity.doc | 1220 +++++++++++++++++ .../widget/NoteWidgetProvider.doc | 169 +++ .../widget/NoteWidgetProvider_2x.doc | 48 + .../widget/NoteWidgetProvider_4x.doc | 58 + 8 files changed, 2475 insertions(+) create mode 100644 doc/精读报告/tool/BackupUtils.doc create mode 100644 doc/精读报告/tool/DataUtils.doc create mode 100644 doc/精读报告/tool/GTaskStringUtils.doc create mode 100644 doc/精读报告/tool/ResourceParser.doc create mode 100644 doc/精读报告/ui/NotesListActivity.doc create mode 100644 doc/精读报告/widget/NoteWidgetProvider.doc create mode 100644 doc/精读报告/widget/NoteWidgetProvider_2x.doc create mode 100644 doc/精读报告/widget/NoteWidgetProvider_4x.doc diff --git a/doc/精读报告/tool/BackupUtils.doc b/doc/精读报告/tool/BackupUtils.doc new file mode 100644 index 0000000..5abf325 --- /dev/null +++ b/doc/精读报告/tool/BackupUtils.doc @@ -0,0 +1,345 @@ +/* + * 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.tool; + +import android.content.Context; +import android.database.Cursor; +import android.os.Environment; +import android.text.TextUtils; +import android.text.format.DateFormat; +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.DataConstants; +import net.micode.notes.data.Notes.NoteColumns; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + + +public class BackupUtils { + private static final String TAG = "BackupUtils";//定义一个常量,用于日志输出的标签 + // Singleton stuff + private static BackupUtils sInstance; // 定义一个静态变量,用于保存单例对象的引用 + + public static synchronized BackupUtils getInstance(Context context) {// 定义一个静态同步方法,用于获取单例对象的实例 + if (sInstance == null) {// 如果单例对象还没有创建 + sInstance = new BackupUtils(context);// 就用传入的上下文参数创建一个新的单例对象 + } + return sInstance;// 返回单例对象的引用 + } + + /** + * Following states are signs to represents backup or restore + * status + */ + // Currently, the sdcard is not mounted + public static final int STATE_SD_CARD_UNMOUONTED = 0;// 定义一个常量,表示当前的状态是 SD 卡没有挂载 + // The backup file not exist + public static final int STATE_BACKUP_FILE_NOT_EXIST = 1;// 定义一个常量,表示当前的状态是备份文件不存在 + // The data is not well formated, may be changed by other programs + public static final int STATE_DATA_DESTROIED = 2;// 定义一个常量,表示当前的状态是数据格式不正确,可能被其他程序修改 + // Some run-time exception which causes restore or backup fails + public static final int STATE_SYSTEM_ERROR = 3;// 定义一个常量,表示当前的状态是系统错误,导致恢复或备份失败 + // Backup or restore success + public static final int STATE_SUCCESS = 4;// 定义一个常量,表示当前的状态是恢复或备份成功 + + private TextExport mTextExport;// 定义一个私有变量,用于保存一个 TextExport 对象的引用 + + private BackupUtils(Context context) { + // 定义一个私有构造器,用于创建 BackupUtils 对象mTextExport = new TextExport(context);// 用传入的上下文参数创建一个 TextExport 对象,并赋值给 mTextExport 变量 + } + + private static boolean externalStorageAvailable() {// 定义一个私有静态方法,用于判断外部存储是否可用 + return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); + } + + public int exportToText() { + // 定义一个公有方法,用于导出文本文件 + return mTextExport.exportToText();//调用 mTextExport 对象的 exportToText 方法,并返回其结果 + } + + public String getExportedTextFileName() {// 定义一个公有方法,用于获取导出的文本文件名 + return mTextExport.mFileName;// 返回 mTextExport 对象的 mFileName 变量的值 + } + + public String getExportedTextFileDir() {// 定义一个公有方法,用于获取导出的文本文件目录 + return mTextExport.mFileDirectory;// 返回 mTextExport 对象的 mFileDirectory 变量的值 + } + + private static class TextExport {// 定义一个私有静态内部类,用于实现文本文件的导出功能 + private static final String[] NOTE_PROJECTION = { // 定义一个私有静态常量数组,用于指定查询笔记表时需要返回的列名 + NoteColumns.ID, + NoteColumns.MODIFIED_DATE, + NoteColumns.SNIPPET, + NoteColumns.TYPE + }; + + private static final int NOTE_COLUMN_ID = 0;// 定义一个私有静态常量,表示笔记 ID 列在 NOTE_PROJECTION 数组中的索引 + + private static final int NOTE_COLUMN_MODIFIED_DATE = 1;// 定义一个私有静态常量,表示笔记修改日期列在 NOTE_PROJECTION 数组中的索引 + + private static final int NOTE_COLUMN_SNIPPET = 2; // 定义一个私有静态常量,表示笔记摘要列在 NOTE_PROJECTION 数组中的索引 + + private static final String[] DATA_PROJECTION = {// 定义一个私有静态常量数组,用于指定查询数据表时需要返回的列名 + DataColumns.CONTENT, + DataColumns.MIME_TYPE, + DataColumns.DATA1, + DataColumns.DATA2, + DataColumns.DATA3, + DataColumns.DATA4, + }; + + private static final int DATA_COLUMN_CONTENT = 0;// 定义一个私有静态常量,表示数据内容列在 DATA_PROJECTION 数组中的索引 + + private static final int DATA_COLUMN_MIME_TYPE = 1;// 定义一个私有静态常量,表示数据 MIME 类型列在 DATA_PROJECTION 数组中的索引 + + private static final int DATA_COLUMN_CALL_DATE = 2;// 定义一个私有静态常量,表示数据 MIME 类型列在 DATA_PROJECTION 数组中的索引 + + private static final int DATA_COLUMN_PHONE_NUMBER = 4;// 定义一个私有静态常量,表示数据 3 列在 DATA_PROJECTION 数组中的索引,用于存储电话号码 + + private final String [] TEXT_FORMAT;// 定义一个私有不可变数组,用于存储文本文件的格式字符串 + private static final int FORMAT_FOLDER_NAME = 0;// 定义一个私有静态常量,表示文件夹名称格式在 TEXT_FORMAT 数组中的索引 + private static final int FORMAT_NOTE_DATE = 1;// 定义一个私有静态常量,表示笔记日期格式在 TEXT_FORMAT 数组中的索引 + private static final int FORMAT_NOTE_CONTENT = 2;// 定义一个私有静态常量,表示笔记内容格式在 TEXT_FORMAT 数组中的索引 + + private Context mContext;// 定义一个私有变量,用于保存上下文对象的引用 + private String mFileName;// 定义一个私有变量,用于保存导出的文本文件名 + private String mFileDirectory;// 定义一个私有变量,用于保存导出的文本文件目录 + + public TextExport(Context context) {// 定义一个公有构造器,用于创建 TextExport 对象 + TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note);// 用传入的上下文参数获取资源数组,并赋值给 TEXT_FORMAT 数组 + mContext = context; // 用传入的上下文参数赋值给 mContext 变量 + mFileName = "";// 初始化 mFileName 变量为空字符串 + mFileDirectory = "";// 初始化 mFileDirectory 变量为空字符串 + } + + private String getFormat(int id) { + return TEXT_FORMAT[id]; + }// 定义一个私有方法,用于根据索引获取格式字符串 + + /** + * Export the folder identified by folder id to text + */ + private void exportFolderToText(String folderId, PrintStream ps) {// 定义一个私有方法,用于导出指定文件夹 ID 的文本文件,需要传入文件夹 ID 和打印流对象作为参数 + // Query notes belong to this folder + Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI,// 用 mContext 变量获取内容解析器,并查询笔记表的 URI + NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] {// 指定需要返回的列名数组为 NOTE_PROJECTION + folderId + }, null); + + if (notesCursor != null) { + if (notesCursor.moveToFirst()) { + do { + // Print note's last modified date + 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);// 用游标获取当前行的笔记 ID 列的值,转换为字符串,并赋值给 noteId 变量 + exportNoteToText(noteId, ps);// 调用 exportNoteToText 方法,传入笔记 ID 和打印流对象作为参数,导出该笔记的文本文件 + } while (notesCursor.moveToNext());// 循环条件为游标移动到下一行,直到没有更多行为止 + } + notesCursor.close();//关闭游标对象,释放资源 + } + } + + /** + * Export note identified by id to a print stream + */ + private void exportNoteToText(String noteId, PrintStream ps) { // 定义一个私有方法,用于导出指定笔记 ID 的文本文件,需要传入笔记 ID 和打印流对象作为参数 + Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI,// 用 mContext 变量获取内容解析器,并查询数据表的 URI + DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] {// 指定查询条件为笔记 ID 等于传入的笔记 ID noteId }, null); // 指定排序方式为 null + noteId + }, null); + + if (dataCursor != null) { // 如果数据游标不为空 + if (dataCursor.moveToFirst()) { // 如果数据游标移动到第一行 + do { + String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); // 获取数据的类型 + if (DataConstants.CALL_NOTE.equals(mimeType)) { // 如果数据是通话记录 + // 打印电话号码 + String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); // 获取电话号码 + long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); // 获取通话日期 + String location = dataCursor.getString(DATA_COLUMN_CONTENT); // 获取通话附件位置 + + if (!TextUtils.isEmpty(phoneNumber)) { // 如果电话号码不为空 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + phoneNumber)); // 格式化并打印电话号码 + } + // 打印通话日期 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat + .format(mContext.getString(R.string.format_datetime_mdhm), + callDate))); // 格式化并打印通话日期 + // 打印通话附件位置 + if (!TextUtils.isEmpty(location)) { // 如果通话附件位置不为空 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + location)); // 格式化并打印通话附件位置 + } + } else if (DataConstants.NOTE.equals(mimeType)) { // 如果数据是便签 + String content = dataCursor.getString(DATA_COLUMN_CONTENT); // 获取便签内容 + if (!TextUtils.isEmpty(content)) { // 如果便签内容不为空 + ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), + content)); // 格式化并打印便签内容 + } + } + } while (dataCursor.moveToNext()); // 循环直到数据游标移动到最后一行 + } + dataCursor.close(); // 关闭数据游标 + } + // print a line separator between note + try { + ps.write(new byte[] { + Character.LINE_SEPARATOR, Character.LETTER_NUMBER + }); // 尝试写入一个字节数组,包含换行符和字母数字 + } catch (IOException e) { // 如果发生输入输出异常 + Log.e(TAG, e.toString()); // 打印错误日志 + } + } + + /** + * Note will be exported as text which is user readable + */ + public int exportToText() { // 定义一个导出文本的方法 + if (!externalStorageAvailable()) { // 如果外部存储不可用 + Log.d(TAG, "Media was not mounted"); // 打印调试日志 + return STATE_SD_CARD_UNMOUONTED; // 返回SD卡未挂载的状态 + } + + PrintStream ps = getExportToTextPrintStream(); // 获取导出文本的打印流 + if (ps == null) { // 如果打印流为空 + Log.e(TAG, "get print stream error"); // 打印错误日志 + return STATE_SYSTEM_ERROR; // 返回系统错误的状态 + } + // 首先导出文件夹和它们的便签 + Cursor folderCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + "(" + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + " AND " + + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + ") OR " + + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER, null, null); // 查询文件夹类型的便签,排除回收站和通话记录文件夹 + + if (folderCursor != null) { // 如果文件夹游标不为空 + if (folderCursor.moveToFirst()) { // 如果文件夹游标移动到第一行 + do { + // 打印文件夹的名字 + String folderName = ""; + if(folderCursor.getLong(NOTE_COLUMN_ID) == Notes.ID_CALL_RECORD_FOLDER) { // 如果文件夹是通话记录文件夹 + folderName = mContext.getString(R.string.call_record_folder_name); // 获取通话记录文件夹的名字 + } else { // 否则 + folderName = folderCursor.getString(NOTE_COLUMN_SNIPPET); // 获取文件夹的摘要作为名字 + } + if (!TextUtils.isEmpty(folderName)) { // 如果文件夹名字不为空 + ps.println(String.format(getFormat(FORMAT_FOLDER_NAME), folderName)); // 格式化并打印文件夹名字 + } + String folderId = folderCursor.getString(NOTE_COLUMN_ID); // 获取文件夹的ID + exportFolderToText(folderId, ps); // 调用导出文件夹到文本的方法,传入文件夹ID和打印流 + } while (folderCursor.moveToNext()); // 循环直到文件夹游标移动到最后一行 + } + folderCursor.close(); // 关闭文件夹游标 + } + + // Export notes in root's folder + Cursor noteCursor = mContext.getContentResolver().query( + Notes.CONTENT_NOTE_URI, + NOTE_PROJECTION, + NoteColumns.TYPE + "=" + +Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + + "=0", null, null); // 查询便签类型的便签,且没有父文件夹 + + if (noteCursor != null) { // 如果便签游标不为空 + if (noteCursor.moveToFirst()) { // 如果便签游标移动到第一行 + do { + ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( + mContext.getString(R.string.format_datetime_mdhm), + noteCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); // 格式化并打印便签的修改日期 + // 查询属于这个便签的数据 + String noteId = noteCursor.getString(NOTE_COLUMN_ID); // 获取便签的ID + exportNoteToText(noteId, ps); // 调用导出便签到文本的方法,传入便签ID和打印流 + } while (noteCursor.moveToNext()); // 循环直到便签游标移动到最后一行 + } + noteCursor.close(); // 关闭便签游标 + } + ps.close(); // 关闭打印流 + + return STATE_SUCCESS; // 返回成功的状态 + } + + /** + * Get a print stream pointed to the file {@generateExportedTextFile} + */ + private PrintStream getExportToTextPrintStream() { // 定义一个获取导出文本的打印流的方法 + File file = generateFileMountedOnSDcard(mContext, R.string.file_path, + R.string.file_name_txt_format); // 调用生成挂载在SD卡上的文件的方法,传入上下文,文件路径和文件名格式 + if (file == null) { // 如果文件为空 + Log.e(TAG, "create file to exported failed"); // 打印错误日志 + return null; // 返回空值 + } + mFileName = file.getName(); // 获取文件的名字 + mFileDirectory = mContext.getString(R.string.file_path); // 获取文件的目录 + PrintStream ps = null; // 声明一个打印流变量 + try { + FileOutputStream fos = new FileOutputStream(file); // 创建一个文件输出流,传入文件 + ps = new PrintStream(fos); // 创建一个打印流,传入文件输出流 + } catch (FileNotFoundException e) { // 如果发生文件未找到异常 + e.printStackTrace(); // 打印异常堆栈 + return null; // 返回空值 + } catch (NullPointerException e) { // 如果发生空指针异常 + e.printStackTrace(); // 打印异常堆栈 + return null; // 返回空值 + } + return ps; // 返回打印流 + } + } + + /** + * Generate the text file to store imported data + */ + private static File generateFileMountedOnSDcard(Context context, int filePathResId, int fileNameFormatResId) { // 定义一个生成挂载在SD卡上的文件的方法,传入上下文,文件路径资源ID和文件名格式资源ID + StringBuilder sb = new StringBuilder(); // 创建一个字符串构建器 + sb.append(Environment.getExternalStorageDirectory()); // 追加外部存储目录 + sb.append(context.getString(filePathResId)); // 追加文件路径字符串 + File filedir = new File(sb.toString()); // 创建一个文件目录对象,传入字符串构建器的内容 + sb.append(context.getString( + fileNameFormatResId, + DateFormat.format(context.getString(R.string.format_date_ymd), + System.currentTimeMillis()))); // 追加文件名字符串,根据日期格式化 + File file = new File(sb.toString()); // 创建一个文件对象,传入字符串构建器的内容 + + try { + if (!filedir.exists()) { // 如果文件目录不存在 + filedir.mkdir(); // 创建文件目录 + } + if (!file.exists()) { // 如果文件不存在 + file.createNewFile(); // 创建新文件 + } + return file; // 返回文件对象 + } catch (SecurityException e) { // 如果发生安全异常 + e.printStackTrace(); // 打印异常堆栈 + } catch (IOException e) { // 如果发生输入输出异常 + e.printStackTrace(); // 打印异常堆栈 + } + + return null; // 返回空值 + } +} + + diff --git a/doc/精读报告/tool/DataUtils.doc b/doc/精读报告/tool/DataUtils.doc new file mode 100644 index 0000000..472fd39 --- /dev/null +++ b/doc/精读报告/tool/DataUtils.doc @@ -0,0 +1,306 @@ +/* + * 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.tool; + +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.OperationApplicationException; +import android.database.Cursor; +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.NoteColumns; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; + +import java.util.ArrayList; +import java.util.HashSet; + + +public class DataUtils { // 定义一个数据工具类 + public static final String TAG = "DataUtils"; // 定义一个静态常量字符串,表示日志标签 + public static boolean batchDeleteNotes(ContentResolver resolver, HashSet ids) { // 定义一个静态方法,批量删除便签,传入内容解析器和便签ID的集合 + if (ids == null) { // 如果ID集合为空 + Log.d(TAG, "the ids is null"); // 打印调试日志 + return true; // 返回真值 + } + if (ids.size() == 0) { // 如果ID集合的大小为零 + Log.d(TAG, "no id is in the hashset"); // 打印调试日志 + return true; // 返回真值 + } + + ArrayList operationList = new ArrayList(); // 创建一个内容提供者操作的列表 + for (long id : ids) { // 遍历ID集合中的每个ID + if(id == Notes.ID_ROOT_FOLDER) { // 如果ID是根文件夹的ID + Log.e(TAG, "Don't delete system folder root"); // 打印错误日志 + continue; // 跳过本次循环 + } + ContentProviderOperation.Builder builder = ContentProviderOperation + .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); // 创建一个内容提供者操作的构建器,指定删除便签的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()); // 打印调试日志,显示失败的ID集合 + return false; // 返回假值 + } + return true; // 返回真值 + } catch (RemoteException e) { // 如果发生远程异常 + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 打印错误日志,显示异常信息 + } catch (OperationApplicationException e) { // 如果发生操作应用异常 + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 打印错误日志,显示异常信息 + } + return false; // 返回假值 + } + + public static void moveNoteToFoler(ContentResolver resolver, long id, long srcFolderId, long desFolderId) { // 定义一个静态方法,移动便签到文件夹,传入内容解析器,便签ID,源文件夹ID和目标文件夹ID + ContentValues values = new ContentValues(); // 创建一个内容值对象 + values.put(NoteColumns.PARENT_ID, desFolderId); // 把目标文件夹ID作为父ID放入内容值中 + values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId); // 把源文件夹ID作为原始父ID放入内容值中 + values.put(NoteColumns.LOCAL_MODIFIED, 1); // 把本地修改标志设为1放入内容值中 + resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null); // 调用内容解析器的更新方法,传入便签的URI和ID,内容值,空的选择和选择参数 + } + + public static boolean batchMoveToFolder(ContentResolver resolver, HashSet ids, + long folderId) { // 定义一个静态方法,批量移动到文件夹,传入内容解析器,便签ID的集合和文件夹ID + if (ids == null) { // 如果ID集合为空 + Log.d(TAG, "the ids is null"); // 打印调试日志 + return true; // 返回真值 + } + + ArrayList operationList = new ArrayList(); // 创建一个内容提供者操作的列表 + for (long id : ids) { // 遍历ID集合中的每个ID + ContentProviderOperation.Builder builder = ContentProviderOperation + .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id)); // 创建一个内容提供者操作的构建器,指定更新便签的URI和ID + builder.withValue(NoteColumns.PARENT_ID, folderId); // 把文件夹ID作为父ID放入构建器中 + builder.withValue(NoteColumns.LOCAL_MODIFIED, 1); // 把本地修改标志设为1放入构建器中 + 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()); // 打印调试日志,显示失败的ID集合 + return false; // 返回假值 + } + return true; // 返回真值 + } catch (RemoteException e) { // 如果发生远程异常 + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 打印错误日志,显示异常信息 + } catch (OperationApplicationException e) { // 如果发生操作应用异常 + Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); // 打印错误日志,显示异常信息 + } + return false; // 返回假值 + } + + /** + * Get the all folder count except system folders {@link Notes#TYPE_SYSTEM}} + */ + public static int getUserFolderCount(ContentResolver resolver) { // 定义一个静态方法,获取用户文件夹的数量,传入内容解析器 + Cursor cursor =resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { "COUNT(*)" }, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, + null); // 查询便签的URI,返回文件夹类型且不在回收站的便签的数量 + + int count = 0; // 声明一个整型变量,表示数量 + if(cursor != null) { // 如果游标不为空 + if(cursor.moveToFirst()) { // 如果游标移动到第一行 + try { + count = cursor.getInt(0); // 获取游标的第一列的值,即数量 + } catch (IndexOutOfBoundsException e) { // 如果发生索引越界异常 + Log.e(TAG, "get folder count failed:" + e.toString()); // 打印错误日志,显示异常信息 + } finally { + cursor.close(); // 最终关闭游标 + } + } + } + return count; // 返回数量 + } + + public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) { // 定义一个静态方法,判断便签是否在数据库中可见,传入内容解析器,便签ID和类型 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, + NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER, + new String [] {String.valueOf(type)}, + null); // 查询便签的URI和ID,返回指定类型且不在回收站的便签 + + boolean exist = false; // 声明一个布尔型变量,表示是否存在 + if (cursor != null) { // 如果游标不为空 + if (cursor.getCount() > 0) { // 如果游标的数量大于零 + exist = true; // 把存在设为真值 + } + cursor.close(); // 关闭游标 + } + return exist; // 返回是否存在 + } + + public static boolean existInNoteDatabase(ContentResolver resolver, long noteId) { + // 查询便签的URI和ID,返回便签的所有列 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId), + null, null, null, null); + + boolean exist = false; // 声明一个布尔型变量,表示是否存在 + if (cursor != null) { // 如果游标不为空 + if (cursor.getCount() > 0) { // 如果游标的数量大于零 + exist = true; // 把存在设为真值 + } + cursor.close(); // 关闭游标 + } + return exist; // 返回是否存在 + } + + + public static boolean existInDataDatabase(ContentResolver resolver, long dataId) { + // 查询数据的URI和ID,返回数据的所有列 + Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId), + null, null, null, null); + + boolean exist = false; // 声明一个布尔型变量,表示是否存在 + if (cursor != null) { // 如果游标不为空 + if (cursor.getCount() > 0) { // 如果游标的数量大于零 + exist = true; // 把存在设为真值 + } + cursor.close(); // 关闭游标 + } + return exist; // 返回是否存在 + } + + public static boolean checkVisibleFolderName(ContentResolver resolver, String name) { + // 查询便签的URI,返回文件夹类型且不在回收站且名称等于指定值的便签 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, null, + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + + " 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) { // 如果游标的数量大于零 + exist = true; // 把存在设为真值 + } + cursor.close(); // 关闭游标 + } + return exist; // 返回是否存在 + } + public static HashSet getFolderNoteWidget(ContentResolver resolver, long folderId) { + // 查询便签的URI,返回指定父ID的便签的小部件ID和类型 + Cursor c = resolver.query(Notes.CONTENT_NOTE_URI, + new String[] { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE }, + NoteColumns.PARENT_ID + "=?", + new String[] { String.valueOf(folderId) }, + null); + + HashSet set = null; // 声明一个哈希集合,用于存储便签小部件的属性 + if (c != null) { // 如果游标不为空 + if (c.moveToFirst()) { // 如果游标移动到第一行 + set = new HashSet(); // 创建一个新的哈希集合 + do { + try { + AppWidgetAttribute widget = new AppWidgetAttribute(); // 创建一个新的便签小部件属性对象 + widget.widgetId = c.getInt(0); // 获取游标的第一列的值,即小部件ID + widget.widgetType = c.getInt(1); // 获取游标的第二列的值,即小部件类型 + set.add(widget); // 把便签小部件属性对象添加到哈希集合中 + } catch (IndexOutOfBoundsException e) { // 如果发生索引越界异常 + Log.e(TAG, e.toString()); // 打印错误日志,显示异常信息 + } + } while (c.moveToNext()); // 当游标移动到下一行时,重复上述操作 + } + c.close(); // 关闭游标 + } + return set; // 返回哈希集合 + } + + + public static String getCallNumberByNoteId(ContentResolver resolver, long noteId) { + // 查询数据的URI,返回指定便签ID和MIME类型的数据的电话号码 + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.PHONE_NUMBER }, + CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?", + new String [] { String.valueOf(noteId), CallNote.CONTENT_ITEM_TYPE }, + null); + + if (cursor != null && cursor.moveToFirst()) { // 如果游标不为空且移动到第一行 + try { + return cursor.getString(0); // 返回游标的第一列的值,即电话号码 + } catch (IndexOutOfBoundsException e) { // 如果发生索引越界异常 + Log.e(TAG, "Get call number fails " + e.toString()); // 打印错误日志,显示异常信息 + } finally { + cursor.close(); // 最终关闭游标 + } + } + return ""; // 返回空字符串 + } + + public static long getNoteIdByPhoneNumberAndCallDate(ContentResolver resolver, String phoneNumber, long callDate) { + // 查询数据的URI,返回指定通话日期、MIME类型和电话号码的数据的便签ID + Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI, + new String [] { CallNote.NOTE_ID }, + CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND PHONE_NUMBERS_EQUAL(" + + CallNote.PHONE_NUMBER + ",?)", + new String [] { String.valueOf(callDate), CallNote.CONTENT_ITEM_TYPE, phoneNumber }, + null); + + if (cursor != null) { // 如果游标不为空 + if (cursor.moveToFirst()) { // 如果游标移动到第一行 + try { + return cursor.getLong(0); // 返回游标的第一列的值,即便签ID + } catch (IndexOutOfBoundsException e) { // 如果发生索引越界异常 + Log.e(TAG, "Get call note id fails " + e.toString()); // 打印错误日志,显示异常信息 + } + } + cursor.close(); // 关闭游标 + } + return 0; // 返回0 + } + + + public static String getSnippetById(ContentResolver resolver, long noteId) { + // 查询便签的URI,返回指定ID的便签的摘要 + Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI, + new String [] { NoteColumns.SNIPPET }, + NoteColumns.ID + "=?", + new String [] { String.valueOf(noteId)}, + null); + + if (cursor != null) { // 如果游标不为空 + String snippet = ""; // 声明一个字符串变量,表示摘要 + if (cursor.moveToFirst()) { // 如果游标移动到第一行 + snippet = cursor.getString(0); // 获取游标的第一列的值,即摘要 + } + cursor.close(); // 关闭游标 + return snippet; // 返回摘要 + } + throw new IllegalArgumentException("Note is not found with id: " + noteId); // 抛出非法参数异常,显示错误信息 + } + + + public static String getFormattedSnippet(String snippet) { + if (snippet != null) { // 如果摘要不为空 + snippet = snippet.trim(); // 去掉摘要两端的空格 + int index = snippet.indexOf('\n'); // 查找摘要中第一个换行符的位置 + if (index != -1) { // 如果找到了换行符 + snippet = snippet.substring(0, index); // 截取换行符之前的部分作为新的摘要 + } + } + return snippet; // 返回格式化后的摘要字符串 + } +} diff --git a/doc/精读报告/tool/GTaskStringUtils.doc b/doc/精读报告/tool/GTaskStringUtils.doc new file mode 100644 index 0000000..a147377 --- /dev/null +++ b/doc/精读报告/tool/GTaskStringUtils.doc @@ -0,0 +1,115 @@ +/* + * 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.tool; + +public class GTaskStringUtils { + + // 定义一些常量字符串,表示Google任务的JSON格式的属性名 + + public final static String GTASK_JSON_ACTION_ID = "action_id"; // 动作ID + + public final static String GTASK_JSON_ACTION_LIST = "action_list"; // 动作列表 + + public final static String GTASK_JSON_ACTION_TYPE = "action_type"; // 动作类型 + + public final static String GTASK_JSON_ACTION_TYPE_CREATE = "create"; // 创建动作 + + public final static String GTASK_JSON_ACTION_TYPE_GETALL = "get_all"; // 获取所有动作 + + public final static String GTASK_JSON_ACTION_TYPE_MOVE = "move"; // 移动动作 + + public final static String GTASK_JSON_ACTION_TYPE_UPDATE = "update"; // 更新动作 + + public final static String GTASK_JSON_CREATOR_ID = "creator_id"; // 创建者ID + + public final static String GTASK_JSON_CHILD_ENTITY = "child_entity"; // 子实体 + + public final static String GTASK_JSON_CLIENT_VERSION = "client_version"; // 客户端版本 + + public final static String GTASK_JSON_COMPLETED = "completed"; // 完成状态 + + public final static String GTASK_JSON_CURRENT_LIST_ID = "current_list_id"; // 当前列表ID + + public final static String GTASK_JSON_DEFAULT_LIST_ID = "default_list_id"; // 默认列表ID + + public final static String GTASK_JSON_DELETED = "deleted"; // 删除状态 + + public final static String GTASK_JSON_DEST_LIST = "dest_list"; // 目标列表 + + public final static String GTASK_JSON_DEST_PARENT = "dest_parent"; // 目标父实体 + + public final static String GTASK_JSON_DEST_PARENT_TYPE = "dest_parent_type"; // 目标父实体类型 + + public final static String GTASK_JSON_ENTITY_DELTA = "entity_delta"; // 实体变化 + + public final static String GTASK_JSON_ENTITY_TYPE = "entity_type"; // 实体类型 + + public final static String GTASK_JSON_GET_DELETED = "get_deleted"; // 获取删除状态 + + public final static String GTASK_JSON_ID = "id"; // ID + + public final static String GTASK_JSON_INDEX = "index"; // 索引 + + public final static String GTASK_JSON_LAST_MODIFIED = "last_modified"; // 最后修改时间 + + public final static String GTASK_JSON_LATEST_SYNC_POINT = "latest_sync_point"; // 最新同步点 + + public final static String GTASK_JSON_LIST_ID = "list_id"; // 列表ID + + public final static String GTASK_JSON_LISTS = "lists"; // 列表 + + public final static String GTASK_JSON_NAME = "name"; // 名称 + + public final static String GTASK_JSON_NEW_ID = "new_id"; // 新ID + + public final static String GTASK_JSON_NOTES = "notes"; // 便签 + + public final static String GTASK_JSON_PARENT_ID = "parent_id"; // 父ID + + public final static String GTASK_JSON_PRIOR_SIBLING_ID = "prior_sibling_id"; // 前一个兄弟ID + + public final static String GTASK_JSON_RESULTS = "results"; // 结果 + + public final static String GTASK_JSON_SOURCE_LIST = "source_list"; // 源列表 + + public final static String GTASK_JSON_TASKS = "tasks"; // 任务 + + public final static String GTASK_JSON_TYPE = "type"; // 类型 + + public final static String GTASK_JSON_TYPE_GROUP = "GROUP"; // 组类型 + + public final static String GTASK_JSON_TYPE_TASK = "TASK"; // 任务类型 + + public final static String GTASK_JSON_USER = "user"; // 用户 + + public final static String MIUI_FOLDER_PREFFIX = "[MIUI_Notes]"; // MIUI文件夹的前缀 + + public final static String FOLDER_DEFAULT = "Default"; // 默认文件夹的名称 + + public final static String FOLDER_CALL_NOTE = "Call_Note"; // 通话便签文件夹的名称 + + public final static String FOLDER_META = "METADATA"; // 元数据文件夹的名称 + + public final static String META_HEAD_GTASK_ID = "meta_gid"; // 元数据中的Google任务ID的头部 + + public final static String META_HEAD_NOTE = "meta_note"; // 元数据中的便签的头部 + + public final static String META_HEAD_DATA = "meta_data"; // 元数据中的数据的头部 + + public final static String META_NOTE_NAME = "[META INFO] DON'T UPDATE AND DELETE"; // 元数据便签的名称,提示不要更新和删除 + +} diff --git a/doc/精读报告/tool/ResourceParser.doc b/doc/精读报告/tool/ResourceParser.doc new file mode 100644 index 0000000..2708d61 --- /dev/null +++ b/doc/精读报告/tool/ResourceParser.doc @@ -0,0 +1,214 @@ +/* + * 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.tool; + +import android.content.Context; +import android.preference.PreferenceManager; + +import net.micode.notes.R; +import net.micode.notes.ui.NotesPreferenceActivity; + +public class ResourceParser { + + // 定义一些常量整型,表示便签的背景颜色 + public static final int YELLOW = 0; + public static final int BLUE = 1; + public static final int WHITE = 2; + public static final int GREEN = 3; + public static final int RED = 4; + + // 定义一个常量整型,表示默认的背景颜色 + public static final int BG_DEFAULT_COLOR = YELLOW; + + // 定义一些常量整型,表示便签的文字大小 + public static final int TEXT_SMALL = 0; + public static final int TEXT_MEDIUM = 1; + public static final int TEXT_LARGE = 2; + public static final int TEXT_SUPER = 3; + + // 定义一个常量整型,表示默认的文字大小 + public static final int BG_DEFAULT_FONT_SIZE = TEXT_MEDIUM; + + // 定义一个静态内部类,用于存储便签的背景资源 + public static class NoteBgResources { + // 定义一个静态整型数组,表示编辑模式下的便签背景资源 + private final static int [] BG_EDIT_RESOURCES = new int [] { + R.drawable.edit_yellow, + R.drawable.edit_blue, + R.drawable.edit_white, + R.drawable.edit_green, + R.drawable.edit_red + }; + + // 定义一个静态整型数组,表示编辑模式下的便签标题背景资源 + private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] { + R.drawable.edit_title_yellow, + R.drawable.edit_title_blue, + R.drawable.edit_title_white, + R.drawable.edit_title_green, + R.drawable.edit_title_red + }; + + // 定义一个静态方法,根据ID获取便签背景资源 + public static int getNoteBgResource(int id) { + return BG_EDIT_RESOURCES[id]; + } + + // 定义一个静态方法,根据ID获取便签标题背景资源 + public static int getNoteTitleBgResource(int id) { + return BG_EDIT_TITLE_RESOURCES[id]; + } + } + + // 定义一个静态方法,获取默认的背景ID + public static int getDefaultBgId(Context context) { + // 如果用户设置了随机背景颜色 + if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean( + NotesPreferenceActivity.PREFERENCE_SET_BG_COLOR_KEY, false)) { + // 返回一个随机的背景ID + return (int) (Math.random() * NoteBgResources.BG_EDIT_RESOURCES.length); + } else { + // 否则返回默认的背景ID + return BG_DEFAULT_COLOR; + } + } + + // 这是一个公共静态类,用于存储笔记项的背景资源 + public static class NoteItemBgResources { + // 这是一个整型数组,用于存储第一个笔记项的背景资源 + private final static int [] BG_FIRST_RESOURCES = new int [] { + R.drawable.list_yellow_up, + R.drawable.list_blue_up, + R.drawable.list_white_up, + R.drawable.list_green_up, + R.drawable.list_red_up + }; + + // 这是一个整型数组,用于存储中间笔记项的背景资源 + private final static int [] BG_NORMAL_RESOURCES = new int [] { + R.drawable.list_yellow_middle, + R.drawable.list_blue_middle, + R.drawable.list_white_middle, + R.drawable.list_green_middle, + R.drawable.list_red_middle + }; + + // 这是一个整型数组,用于存储最后一个笔记项的背景资源 + private final static int [] BG_LAST_RESOURCES = new int [] { + R.drawable.list_yellow_down, + R.drawable.list_blue_down, + R.drawable.list_white_down, + R.drawable.list_green_down, + R.drawable.list_red_down, + }; + + // 这是一个整型数组,用于存储单个笔记项的背景资源 + private final static int [] BG_SINGLE_RESOURCES = new int [] { + R.drawable.list_yellow_single, + R.drawable.list_blue_single, + R.drawable.list_white_single, + R.drawable.list_green_single, + R.drawable.list_red_single + }; + + // 这是一个公共静态方法,用于根据id返回第一个笔记项的背景资源 + public static int getNoteBgFirstRes(int id) { + return BG_FIRST_RESOURCES[id]; + } + + // 这是一个公共静态方法,用于根据id返回最后一个笔记项的背景资源 + public static int getNoteBgLastRes(int id) { + return BG_LAST_RESOURCES[id]; + } + + // 这是一个公共静态方法,用于根据id返回单个笔记项的背景资源 + public static int getNoteBgSingleRes(int id) { + return BG_SINGLE_RESOURCES[id]; + } + + // 这是一个公共静态方法,用于根据id返回中间笔记项的背景资源 + public static int getNoteBgNormalRes(int id) { + return BG_NORMAL_RESOURCES[id]; + } + + // 这是一个公共静态方法,用于返回文件夹的背景资源 + // 这是一个公共静态方法,用于返回文件夹的背景资源 + public static int getFolderBgRes() { + return R.drawable.list_folder; + } + } + + // 这是一个公共静态类,用于存储小部件的背景资源 + public static class WidgetBgResources { + // 这是一个整型数组,用于存储2x2小部件的背景资源 + private final static int [] BG_2X_RESOURCES = new int [] { + R.drawable.widget_2x_yellow, + R.drawable.widget_2x_blue, + R.drawable.widget_2x_white, + R.drawable.widget_2x_green, + R.drawable.widget_2x_red, + }; + + // 这是一个公共静态方法,用于根据id返回2x2小部件的背景资源 + public static int getWidget2xBgResource(int id) { + return BG_2X_RESOURCES[id]; + } + + // 这是一个整型数组,用于存储4x4小部件的背景资源 + private final static int [] BG_4X_RESOURCES = new int [] { + R.drawable.widget_4x_yellow, + R.drawable.widget_4x_blue, + R.drawable.widget_4x_white, + R.drawable.widget_4x_green, + R.drawable.widget_4x_red + }; + + // 这是一个公共静态方法,用于根据id返回4x4小部件的背景资源 + public static int getWidget4xBgResource(int id) { + return BG_4X_RESOURCES[id]; + } + } + + // 这是一个公共静态类,用于存储文本外观的资源 + public static class TextAppearanceResources { + // 这是一个整型数组,用于存储不同大小的文本外观资源 + private final static int [] TEXTAPPEARANCE_RESOURCES = new int [] { + R.style.TextAppearanceNormal, + R.style.TextAppearanceMedium, + R.style.TextAppearanceLarge, + R.style.TextAppearanceSuper + }; + + // 这是一个公共静态方法,用于根据id返回文本外观资源 + public static int getTexAppearanceResource(int id) { + /** + * HACKME: Fix bug of store the resource id in shared preference. + * The id may larger than the length of resources, in this case, + * return the {@link ResourceParser#BG_DEFAULT_FONT_SIZE} + */ + if (id >= TEXTAPPEARANCE_RESOURCES.length) { + return BG_DEFAULT_FONT_SIZE; + } + return TEXTAPPEARANCE_RESOURCES[id]; + } + + // 这是一个公共静态方法,用于返回文本外观资源的大小 + public static int getResourcesSize() { + return TEXTAPPEARANCE_RESOURCES.length; + } + } +} diff --git a/doc/精读报告/ui/NotesListActivity.doc b/doc/精读报告/ui/NotesListActivity.doc new file mode 100644 index 0000000..784995a --- /dev/null +++ b/doc/精读报告/ui/NotesListActivity.doc @@ -0,0 +1,1220 @@ +/* + * 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.ui; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.appwidget.AppWidgetManager; +import android.content.AsyncQueryHandler; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.os.AsyncTask; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.ActionMode; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.Display; +import android.view.HapticFeedbackConstants; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnCreateContextMenuListener; +import android.view.View.OnTouchListener; +import android.view.inputmethod.InputMethodManager; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.AdapterView.OnItemLongClickListener; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.PopupMenu; +import android.widget.TextView; +import android.widget.Toast; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.gtask.remote.GTaskSyncService; +import net.micode.notes.model.WorkingNote; +import net.micode.notes.tool.BackupUtils; +import net.micode.notes.tool.DataUtils; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute; +import net.micode.notes.widget.NoteWidgetProvider_2x; +import net.micode.notes.widget.NoteWidgetProvider_4x; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashSet; + +// 定义一个类,继承自Activity类,实现OnClickListener和OnItemLongClickListener接口 +public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener { + // 定义一个常量,表示文件夹笔记列表查询的标识符 + private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0; + + // 定义一个常量,表示文件夹列表查询的标识符 + private static final int FOLDER_LIST_QUERY_TOKEN = 1; + + // 定义一个常量,表示菜单中删除文件夹的选项 + private static final int MENU_FOLDER_DELETE = 0; + + // 定义一个常量,表示菜单中查看文件夹的选项 + private static final int MENU_FOLDER_VIEW = 1; + + // 定义一个常量,表示菜单中修改文件夹名称的选项 + private static final int MENU_FOLDER_CHANGE_NAME = 2; + + // 定义一个常量,表示偏好设置中添加介绍的选项 + private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; + + // 定义一个枚举类型,表示列表编辑的状态,有三种可能:笔记列表、子文件夹、通话记录文件夹 + private enum ListEditState { + NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER + }; + + // 定义一个变量,表示当前的列表编辑状态 + private ListEditState mState; + + // 定义一个变量,表示后台查询处理器 + private BackgroundQueryHandler mBackgroundQueryHandler; + + // 定义一个变量,表示笔记列表适配器 + private NotesListAdapter mNotesListAdapter; + + // 定义一个变量,表示笔记列表视图 + private ListView mNotesListView; + + private Button mAddNewNote; // 添加新便签的按钮 + private boolean mDispatch; // 用于判断是否需要分发触摸事件 + private int mOriginY; // 用于记录触摸事件的原始 Y 坐标 + private int mDispatchY; // 用于记录分发触摸事件的 Y 坐标 + private TextView mTitleBar; // 用于显示标题栏的文本视图 + private long mCurrentFolderId; // 用于记录当前文件夹的 ID + private ContentResolver mContentResolver; // 用于访问内容提供器的对象 + private ModeCallback mModeCallBack; // 用于处理上下文菜单的回调对象 + private static final String TAG = "NotesListActivity"; // 定义一个常量字符串,用于日志输出 + + public static final int NOTES_LISTVIEW_SCROLL_RATE = 30; // 定义一个常量整数,用于设置便签列表视图的滚动速率 + + private NoteItemData mFocusNoteDataItem; // 用于记录当前焦点便签的数据对象 + + // 定义一些常量字符串,用于查询便签数据库的条件 + private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?"; + private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + + " AND " + NoteColumns.NOTES_COUNT + ">0)"; + + // 定义一些常量整数,用于标识不同的请求码 + private final static int REQUEST_CODE_OPEN_NODE = 102; + private final static int REQUEST_CODE_NEW_NODE = 103; + + @Override + protected void onCreate(Bundle savedInstanceState) {// 调用父类的方法 + super.onCreate(savedInstanceState);// 设置布局文件为note_list.xml + + setContentView(R.layout.note_list);// 初始化资源 + initResources(); + + /** + * Insert an introduction when user firstly use this application + */ + setAppInfoFromRawRes(); // 从原始资源文件中设置应用程序的介绍信息 + } + + @Override + // 这个方法是在一个Activity从另一个Activity返回结果时调用的 + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + // 如果结果是成功的,并且请求码是打开或新建一个节点,那么就更新列表适配器的数据源 + if (resultCode == RESULT_OK + && (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) { + mNotesListAdapter.changeCursor(null); + } else { + // 否则,调用父类的方法处理结果 + super.onActivityResult(requestCode, resultCode, data); + } + } + + // 这个方法是从raw资源文件中读取应用信息,并保存到SharedPreferences中 + private void setAppInfoFromRawRes() { + // 获取SharedPreferences对象 + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + // 如果没有添加过介绍信息,就执行以下操作 + if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) { + // 创建一个StringBuilder对象,用来存储读取的内容 + StringBuilder sb = new StringBuilder(); + // 声明一个输入流对象 + InputStream in = null; + try { + // 从raw资源文件中打开输入流 + in = getResources().openRawResource(R.raw.introduction); + // 如果输入流不为空,就创建一个字符输入流和缓冲输入流,按照字符数组读取内容,并追加到StringBuilder中 + if (in != null) { + InputStreamReader isr = new InputStreamReader(in); + BufferedReader br = new BufferedReader(isr); + char [] buf = new char[1024]; + int len = 0; + while ((len = br.read(buf)) > 0) { + sb.append(buf, 0, len); + } + } else { + // 如果输入流为空,就打印错误日志并返回 + Log.e(TAG, "Read introduction file error"); + return; + } + } catch (IOException e) { + // 如果发生异常,就打印堆栈信息并返回 + e.printStackTrace(); + return; + } finally { + // 最后,如果输入流不为空,就关闭输入流 + if(in != null) { + try { + in.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + // 这个代码段是在读取完介绍信息后,创建一个空的WorkingNote对象,并设置其属性和内容 + WorkingNote note = WorkingNote.createEmptyNote(this, Notes.ID_ROOT_FOLDER, + AppWidgetManager.INVALID_APPWIDGET_ID, Notes.TYPE_WIDGET_INVALIDE, + ResourceParser.RED); + // 设置WorkingNote对象的文本内容为StringBuilder中的内容 + note.setWorkingText(sb.toString()); + // 如果保存WorkingNote对象成功,就把SharedPreferences中的添加介绍信息的标志设为true + if (note.saveNote()) { + sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit(); + } else { + // 如果保存失败,就打印错误日志并返回 + Log.e(TAG, "Save introduction note error"); + return; + } + } + } + + @Override + // 这个方法是在Activity启动时调用的 + protected void onStart() { + // 调用父类的方法 + super.onStart(); + // 开始异步查询笔记列表 + startAsyncNotesListQuery(); + } + + // 这个方法是初始化资源的 + private void initResources() { + // 获取内容解析器对象 + mContentResolver = this.getContentResolver(); + // 创建一个后台查询处理器对象 + mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver()); + // 设置当前文件夹的ID为根文件夹的ID + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + // 获取笔记列表视图对象,并设置其底部视图和点击监听器 + mNotesListView = (ListView) findViewById(R.id.notes_list); + mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null), + null, false); + mNotesListView.setOnItemClickListener(new OnListItemClickListener()); + mNotesListView.setOnItemLongClickListener(this); + // 创建一个笔记列表适配器对象,并设置给笔记列表视图 + mNotesListAdapter = new NotesListAdapter(this); + mNotesListView.setAdapter(mNotesListAdapter); + // 获取添加新笔记按钮对象,并设置其点击监听器和触摸监听器 + mAddNewNote = (Button) findViewById(R.id.btn_new_note); + mAddNewNote.setOnClickListener(this); + mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener()); + // 初始化一些变量,用来控制事件分发和标题栏显示 + mDispatch = false; + mDispatchY = 0; + mOriginY = 0; + mTitleBar = (TextView) findViewById(R.id.tv_title_bar); + // 设置当前的列表编辑状态为笔记列表状态 + mState = ListEditState.NOTE_LIST; + // 创建一个模式回调对象,用来处理上下文菜单的操作 + mModeCallBack = new ModeCallback(); + } + + // 这个内部类实现了多选模式监听器和菜单项点击监听器的接口,用来处理列表视图的多选模式和菜单操作 + private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener { + // 声明一个下拉菜单对象,一个操作模式对象和一个移动菜单项对象 + private DropdownMenu mDropDownMenu; + private ActionMode mActionMode; + private MenuItem mMoveMenu; + + // 这个方法是在创建操作模式时调用的 + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + // 从资源文件中加载菜单项,并设置删除和移动菜单项的点击监听器 + getMenuInflater().inflate(R.menu.note_list_options, menu); + menu.findItem(R.id.delete).setOnMenuItemClickListener(this); + mMoveMenu = menu.findItem(R.id.move); + // 如果当前的文件夹是通话记录文件夹或者用户没有自定义文件夹,就隐藏移动菜单项 + if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER + || DataUtils.getUserFolderCount(mContentResolver) == 0) { + mMoveMenu.setVisible(false); + } else { + // 否则,显示移动菜单项,并设置其点击监听器 + mMoveMenu.setVisible(true); + mMoveMenu.setOnMenuItemClickListener(this); + } + // 保存操作模式对象的引用,并设置列表适配器的选择模式为true + mActionMode = mode; + mNotesListAdapter.setChoiceMode(true); + // 设置列表视图不可长按,并隐藏添加新笔记按钮 + mNotesListView.setLongClickable(false); + mAddNewNote.setVisibility(View.GONE); + + // 从布局文件中加载自定义视图,并设置给操作模式对象 + View customView = LayoutInflater.from(NotesListActivity.this).inflate( + R.layout.note_list_dropdown_menu, null); + mode.setCustomView(customView); + // 创建一个下拉菜单对象,并设置其按钮和菜单资源 + mDropDownMenu = new DropdownMenu(NotesListActivity.this, + (Button) customView.findViewById(R.id.selection_menu), + R.menu.note_list_dropdown); + // 设置下拉菜单的菜单项点击监听器,用来实现全选或取消全选的功能,并更新菜单状态 + mDropDownMenu.setOnDropdownMenuItemClickListener(new PopupMenu.OnMenuItemClickListener(){ + public boolean onMenuItemClick(MenuItem item) { + mNotesListAdapter.selectAll(!mNotesListAdapter.isAllSelected()); + updateMenu(); + return true; + } + + }); + return true; + } + // 这个方法是更新菜单状态的 + private void updateMenu() { + // 获取已选择的笔记数量 + int selectedCount = mNotesListAdapter.getSelectedCount(); + // 更新下拉菜单的标题,显示已选择的数量 + String format = getResources().getString(R.string.menu_select_title, selectedCount); + mDropDownMenu.setTitle(format); + // 获取下拉菜单中的全选菜单项,并根据是否全选设置其标题和状态 + MenuItem item = mDropDownMenu.findItem(R.id.action_select_all); + if (item != null) { + if (mNotesListAdapter.isAllSelected()) { + item.setChecked(true); + item.setTitle(R.string.menu_deselect_all); + } else { + item.setChecked(false); + item.setTitle(R.string.menu_select_all); + } + } + } + + // 这个方法是在准备操作模式时调用的,这里没有实现任何功能 + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + // TODO Auto-generated method stub + return false; + } + + // 这个方法是在点击操作模式中的菜单项时调用的,这里没有实现任何功能 + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + // TODO Auto-generated method stub + return false; + } + + // 这个方法是在销毁操作模式时调用的 + public void onDestroyActionMode(ActionMode mode) { + // 设置列表适配器的选择模式为false,并恢复列表视图的长按功能和添加新笔记按钮的可见性 + mNotesListAdapter.setChoiceMode(false); + mNotesListView.setLongClickable(true); + mAddNewNote.setVisibility(View.VISIBLE); + } + + // 这个方法是结束操作模式的 + public void finishActionMode() { + mActionMode.finish(); + } + + // 这个方法是在列表视图中的某一项被选中或取消选中时调用的 + public void onItemCheckedStateChanged(ActionMode mode, int position, long id, + boolean checked) { + // 设置列表适配器中对应位置的笔记为选中或未选中,并更新菜单状态 + mNotesListAdapter.setCheckedItem(position, checked); + updateMenu(); + } + + // 这个方法是实现菜单项点击监听器的接口,用来处理删除和移动菜单项的点击事件 + public boolean onMenuItemClick(MenuItem item) { + // 如果没有选择任何笔记,就弹出一个提示信息,并返回true + if (mNotesListAdapter.getSelectedCount() == 0) { + Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none), + Toast.LENGTH_SHORT).show(); + return true; + } + + // 根据菜单项的ID,执行相应的操作 + switch (item.getItemId()) { + // 如果是删除菜单项,就弹出一个确认对话框,询问用户是否要删除所选的笔记 + case R.id.delete: + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_notes, + mNotesListAdapter.getSelectedCount())); + // 如果用户点击确定,就调用批量删除的方法 + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, + int which) { + batchDelete(); + } + }); + // 如果用户点击取消,就什么都不做 + builder.setNegativeButton(android.R.string.cancel, null); + // 显示对话框 + builder.show(); + break; + // 如果是移动菜单项,就开始查询目标文件夹的数据 + case R.id.move: + startQueryDestinationFolders(); + break; + // 如果是其他菜单项,就返回false + default: + return false; + } + return true; + } + } + + // 这个内部类实现了触摸监听器的接口,用来处理添加新笔记按钮的触摸事件 + private class NewNoteOnTouchListener implements OnTouchListener { + + // 这个方法是在触摸按钮时调用的 + public boolean onTouch(View v, MotionEvent event) { + // 根据触摸事件的类型,执行相应的操作 + switch (event.getAction()) { + // 如果是按下事件,就执行以下操作 + case MotionEvent.ACTION_DOWN: { + // 获取屏幕的显示对象,并获取屏幕的高度 + Display display = getWindowManager().getDefaultDisplay(); + int screenHeight = display.getHeight(); + // 获取添加新笔记按钮的高度,并计算出按钮的起始位置 + int newNoteViewHeight = mAddNewNote.getHeight(); + int start = screenHeight - newNoteViewHeight; + // 获取触摸事件在屏幕上的Y坐标,并加上按钮的起始位置 + int eventY = start + (int) event.getY(); + /** + * Minus TitleBar's height + */ + // 如果当前的列表编辑状态是子文件夹状态,就减去标题栏的高度 + if (mState == ListEditState.SUB_FOLDER) { + eventY -= mTitleBar.getHeight(); + start -= mTitleBar.getHeight(); + } + + // 如果触摸事件在一个特定的区域内,就执行以下操作 + if (event.getY() < (event.getX() * (-0.12) + 94)) { + // 获取列表视图中最后一个可见的视图对象(除了底部视图) + View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1 + - mNotesListView.getFooterViewsCount()); + // 如果视图对象不为空,并且它的底部位置大于按钮的起始位置,并且它的顶部位置小于按钮的结束位置,就执行以下操作 + if (view != null && view.getBottom() > start + && (view.getTop() < (start + 94))) { + // 保存触摸事件在按钮上的Y坐标和在屏幕上的Y坐标 + mOriginY = (int) event.getY(); + mDispatchY = eventY; + // 设置触摸事件在屏幕上的Y坐标为之前保存的值 + event.setLocation(event.getX(), mDispatchY); + // 设置分发标志为true,并把触摸事件分发给列表视图处理 + mDispatch = true; + return mNotesListView.dispatchTouchEvent(event); + } + } + break; + } + // 如果是移动事件,就执行以下操作 + case MotionEvent.ACTION_MOVE: { + // 如果分发标志为true,就执行以下操作 + if (mDispatch) { + // 更新触摸事件在屏幕上的Y坐标,并设置给触摸事件对象 + mDispatchY += (int) event.getY() - mOriginY; + event.setLocation(event.getX(), mDispatchY); + // 把触摸事件分发给列表视图处理,并返回true + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + // 如果是其他类型的事件,就执行以下操作 + default: { + // 如果分发标志为true,就执行以下操作 + if (mDispatch) { + // 设置触摸事件在屏幕上的Y坐标为之前保存的值,并把分发标志设为false + event.setLocation(event.getX(), mDispatchY); + mDispatch = false; + // 把触摸事件分发给列表视图处理,并返回true + return mNotesListView.dispatchTouchEvent(event); + } + break; + } + } + // 如果没有分发触摸事件,就返回false + return false; + } + + }; + + // 这个方法是开始异步查询笔记列表的 + private void startAsyncNotesListQuery() { + // 根据当前文件夹的ID,设置查询条件 + String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION + : NORMAL_SELECTION; + // 调用后台查询处理器对象,开始查询笔记的数据,并指定查询标识符、投影、条件和排序方式 + mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null, + Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[] { + String.valueOf(mCurrentFolderId) + }, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC"); + } + + // 这个内部类继承了异步查询处理器类,用来处理异步查询的结果 + private final class BackgroundQueryHandler extends AsyncQueryHandler { + // 构造方法,调用父类的构造方法,传入内容解析器对象 + public BackgroundQueryHandler(ContentResolver contentResolver) { + super(contentResolver); + } + + @Override + // 这个方法是在查询完成时调用的,传入查询标识符、对象和游标 + protected void onQueryComplete(int token, Object cookie, Cursor cursor) { + // 根据查询标识符,执行相应的操作 + switch (token) { + // 如果是查询笔记列表的标识符,就把游标传给列表适配器 + case FOLDER_NOTE_LIST_QUERY_TOKEN: + mNotesListAdapter.changeCursor(cursor); + break; + // 如果是查询文件夹列表的标识符,就判断游标是否有效,如果有效,就显示文件夹列表菜单 + case FOLDER_LIST_QUERY_TOKEN: + if (cursor != null && cursor.getCount() > 0) { + showFolderListMenu(cursor); + } else { + // 如果无效,就打印错误日志 + Log.e(TAG, "Query folder failed"); + } + break; + // 如果是其他标识符,就什么都不做 + default: + return; + } + } + } + + // 这个方法是显示文件夹列表菜单的,传入一个游标对象 + private void showFolderListMenu(Cursor cursor) { + // 创建一个对话框构造器对象,并设置其标题 + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + builder.setTitle(R.string.menu_title_select_folder); + // 创建一个文件夹列表适配器对象,并设置给对话框构造器 + final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor); + builder.setAdapter(adapter, new DialogInterface.OnClickListener() { + + // 设置对话框的点击监听器,用来处理用户选择某个文件夹的事件 + public void onClick(DialogInterface dialog, int which) { + // 调用数据工具类的方法,把已选择的笔记批量移动到用户选择的文件夹中 + DataUtils.batchMoveToFolder(mContentResolver, + mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which)); + // 弹出一个提示信息,显示移动了多少笔记到哪个文件夹中 + Toast.makeText( + NotesListActivity.this, + getString(R.string.format_move_notes_to_folder, + mNotesListAdapter.getSelectedCount(), + adapter.getFolderName(NotesListActivity.this, which)), + Toast.LENGTH_SHORT).show(); + // 结束操作模式 + mModeCallBack.finishActionMode(); + } + }); + // 显示对话框 + builder.show(); + } + + private void createNewNote() { + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId); + this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE); + } + + // 定义一个私有方法,用于批量删除笔记 + private void batchDelete() { + // 创建一个异步任务,传入空参数,返回一个AppWidgetAttribute的集合 + new AsyncTask>() { + // 在后台线程执行的方法,返回要更新的小部件的集合 + protected HashSet doInBackground(Void... unused) { + // 获取选中的小部件的集合 + HashSet widgets = mNotesListAdapter.getSelectedWidget(); + // 判断是否是同步模式 + if (!isSyncMode()) { + // 如果不是同步模式,直接删除选中的笔记 + if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter + .getSelectedItemIds())) { + } else { + // 如果删除失败,打印错误日志 + Log.e(TAG, "Delete notes error, should not happens"); + } + } else { + // 如果是同步模式,将选中的笔记移动到回收站文件夹中 + if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter + .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) { + // 如果移动失败,打印错误日志 + Log.e(TAG, "Move notes to trash folder error, should not happens"); + } + } + // 返回要更新的小部件的集合 + return widgets; + } + + @Override + // 在主线程执行的方法,传入要更新的小部件的集合 + protected void onPostExecute(HashSet widgets) { + // 判断小部件集合是否为空 + if (widgets != null) { + // 遍历小部件集合 + for (AppWidgetAttribute widget : widgets) { + // 判断小部件的id和类型是否有效 + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + // 更新小部件的显示内容 + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + // 结束操作模式 + mModeCallBack.finishActionMode(); + } + }.execute(); // 执行异步任务 + } + + // 这个方法是删除一个文件夹的,传入一个文件夹的ID + private void deleteFolder(long folderId) { + // 如果文件夹的ID是根文件夹的ID,就打印错误日志,并返回 + if (folderId == Notes.ID_ROOT_FOLDER) { + Log.e(TAG, "Wrong folder id, should not happen " + folderId); + return; + } + + // 创建一个哈希集合对象,用来存储要删除的文件夹的ID + HashSet ids = new HashSet(); + ids.add(folderId); + // 调用数据工具类的方法,获取该文件夹关联的小部件属性集合 + HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, + folderId); + // 判断是否是同步模式 + if (!isSyncMode()) { + // 如果不是同步模式,就直接批量删除该文件夹 + DataUtils.batchDeleteNotes(mContentResolver, ids); + } else { + // 如果是同步模式,就把该文件夹批量移动到回收站文件夹中 + DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER); + } + // 如果小部件属性集合不为空,就遍历每个小部件属性对象,并更新对应的小部件 + if (widgets != null) { + for (AppWidgetAttribute widget : widgets) { + if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID + && widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) { + updateWidget(widget.widgetId, widget.widgetType); + } + } + } + } + + // 这个方法是打开一个笔记节点的,传入一个笔记项数据对象 + private void openNode(NoteItemData data) { + // 创建一个意图对象,并设置其动作为查看 + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + // 把笔记项数据对象的ID作为额外数据传给意图对象 + intent.putExtra(Intent.EXTRA_UID, data.getId()); + // 用该意图启动一个新的Activity,并指定请求码 + this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); + } + + // 这个方法是打开一个文件夹的,传入一个笔记项数据对象 + private void openFolder(NoteItemData data) { + // 设置当前文件夹的ID为笔记项数据对象的ID,并开始异步查询笔记列表 + mCurrentFolderId = data.getId(); + startAsyncNotesListQuery(); + // 判断笔记项数据对象的ID是否是通话记录文件夹的ID,如果是,就设置当前的列表编辑状态为通话记录文件夹状态,并隐藏添加新笔记按钮 + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mState = ListEditState.CALL_RECORD_FOLDER; + mAddNewNote.setVisibility(View.GONE); + } else { + // 否则,设置当前的列表编辑状态为子文件夹状态 + mState = ListEditState.SUB_FOLDER; + } + // 判断笔记项数据对象的ID是否是通话记录文件夹的ID,如果是,就设置标题栏的文本为通话记录文件夹的名称 + if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) { + mTitleBar.setText(R.string.call_record_folder_name); + } else { + // 否则,设置标题栏的文本为笔记项数据对象的摘要 + mTitleBar.setText(data.getSnippet()); + } + // 设置标题栏为可见 + mTitleBar.setVisibility(View.VISIBLE); + } + + // 这个方法是实现点击监听器的接口,用来处理点击事件 + public void onClick(View v) { + // 根据被点击的视图的ID,执行相应的操作 + switch (v.getId()) { + // 如果是添加新笔记按钮,就调用创建新笔记的方法 + case R.id.btn_new_note: + createNewNote(); + break; + // 如果是其他视图,就什么都不做 + default: + break; + } + } + + // 这个方法是显示软键盘的 + private void showSoftInput() { + // 获取输入法管理器对象 + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + if (inputMethodManager != null) { + // 强制显示软键盘 + inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); + } + } + + // 这个方法是隐藏软键盘的,传入一个视图对象 + private void hideSoftInput(View view) { + // 获取输入法管理器对象 + InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + // 隐藏软键盘,并传入视图对象的窗口标识符 + inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + + // 这个方法是显示创建或修改文件夹的对话框的,传入一个布尔值,表示是否是创建 + private void showCreateOrModifyFolderDialog(final boolean create) { + // 创建一个对话框构造器对象 + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + // 从布局文件中加载一个视图对象,并获取其中的编辑文本对象 + View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null); + final EditText etName = (EditText) view.findViewById(R.id.et_foler_name); + // 显示软键盘 + showSoftInput(); + // 如果不是创建,就执行以下操作 + if (!create) { + // 如果当前的焦点笔记项数据对象不为空,就把它的摘要设置给编辑文本对象,并设置对话框的标题为修改文件夹名称 + if (mFocusNoteDataItem != null) { + etName.setText(mFocusNoteDataItem.getSnippet()); + builder.setTitle(getString(R.string.menu_folder_change_name)); + } else { + // 如果为空,就打印错误日志,并返回 + Log.e(TAG, "The long click data item is null"); + return; + } + } else { + // 如果是创建,就清空编辑文本对象,并设置对话框的标题为创建文件夹 + etName.setText(""); + builder.setTitle(this.getString(R.string.menu_create_folder)); + } + + // 设置对话框的确定按钮,但不设置点击监听器,因为要在后面自定义点击事件的逻辑 + builder.setPositiveButton(android.R.string.ok, null); + // 设置对话框的取消按钮,并设置点击监听器,用来隐藏软键盘 + builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + hideSoftInput(etName); + } + }); + + // 创建并显示对话框,并获取其中的确定按钮对象 + final Dialog dialog = builder.setView(view).show(); + final Button positive = (Button)dialog.findViewById(android.R.id.button1); + // 设置确定按钮的点击监听器,用来处理用户输入的文件夹名称 + positive.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + // 隐藏软键盘 + hideSoftInput(etName); + // 获取编辑文本对象中的内容,并转换为字符串 + String name = etName.getText().toString(); + // 调用数据工具类的方法,检查该文件夹名称是否已经存在,如果存在,就弹出一个提示信息,并选中编辑文本对象中的内容,然后返回 + if (DataUtils.checkVisibleFolderName(mContentResolver, name)) { + Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name), + Toast.LENGTH_LONG).show(); + etName.setSelection(0, etName.length()); + return; + } + // 如果不是创建,就执行以下操作 + if (!create) { + // 如果文件夹名称不为空,就创建一个内容值对象,并设置其摘要、类型和本地修改标志 + if (!TextUtils.isEmpty(name)) { + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + values.put(NoteColumns.LOCAL_MODIFIED, 1); + // 调用内容解析器对象,更新对应的笔记项数据对象 + mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID + + "=?", new String[] { + String.valueOf(mFocusNoteDataItem.getId()) + }); + } + } else if (!TextUtils.isEmpty(name)) { + // 如果是创建,并且文件夹名称不为空,就创建一个内容值对象,并设置其摘要和类型 + ContentValues values = new ContentValues(); + values.put(NoteColumns.SNIPPET, name); + values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER); + // 调用内容解析器对象,插入一个新的笔记项数据对象 + mContentResolver.insert(Notes.CONTENT_NOTE_URI, values); + } + // 关闭对话框 + dialog.dismiss(); + } + }); + + // 如果编辑文本对象中的内容为空,就设置确定按钮为不可用 + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } + /** + * When the name edit text is null, disable the positive button + */ + // 给编辑文本对象添加一个文本变化监听器,用来实时更新确定按钮的状态 + etName.addTextChangedListener(new TextWatcher() { + // 这个方法是在文本变化之前调用的,这里没有实现任何功能 + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + // TODO Auto-generated method stub + + } + + // 这个方法是在文本变化时调用的 + public void onTextChanged(CharSequence s, int start, int before, int count) { + // 如果编辑文本对象中的内容为空,就设置确定按钮为不可用,否则设置为可用 + if (TextUtils.isEmpty(etName.getText())) { + positive.setEnabled(false); + } else { + positive.setEnabled(true); + } + } + + // 这个方法是在文本变化之后调用的,这里没有实现任何功能 + public void afterTextChanged(Editable s) { + // TODO Auto-generated method stub + + } + }); + } + + @Override + // 这个方法是在用户按下返回键时调用的 + public void onBackPressed() { + // 根据当前的列表编辑状态,执行相应的操作 + switch (mState) { + // 如果是子文件夹状态,就把当前文件夹的ID设为根文件夹的ID,并把列表编辑状态设为笔记列表状态,然后开始异步查询笔记列表,并隐藏标题栏 + case SUB_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + startAsyncNotesListQuery(); + mTitleBar.setVisibility(View.GONE); + break; + // 如果是通话记录文件夹状态,就把当前文件夹的ID设为根文件夹的ID,并把列表编辑状态设为笔记列表状态,然后开始异步查询笔记列表,并显示添加新笔记按钮,并隐藏标题栏 + case CALL_RECORD_FOLDER: + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + mAddNewNote.setVisibility(View.VISIBLE); + mTitleBar.setVisibility(View.GONE); + startAsyncNotesListQuery(); + break; + // 如果是笔记列表状态,就调用父类的方法 + case NOTE_LIST: + super.onBackPressed(); + break; + // 如果是其他状态,就什么都不做 + default: + break; + } + } + + // 这个方法是更新小部件的,传入一个小部件的ID和类型 + private void updateWidget(int appWidgetId, int appWidgetType) { + // 创建一个意图对象,并设置其动作为小部件更新 + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); + // 根据小部件的类型,设置意图对象的类为对应的小部件提供器类 + if (appWidgetType == Notes.TYPE_WIDGET_2X) { + intent.setClass(this, NoteWidgetProvider_2x.class); + } else if (appWidgetType == Notes.TYPE_WIDGET_4X) { + intent.setClass(this, NoteWidgetProvider_4x.class); + } else { + // 如果不支持该类型的小部件,就打印错误日志,并返回 + Log.e(TAG, "Unspported widget type"); + return; + } + + // 把小部件的ID作为额外数据传给意图对象 + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] { + appWidgetId + }); + + // 发送广播,通知小部件更新,并设置结果为成功 + sendBroadcast(intent); + setResult(RESULT_OK, intent); + } + + // 这个变量是一个创建上下文菜单的监听器对象,用来处理文件夹的上下文菜单 + private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() { + // 这个方法是在创建上下文菜单时调用的,传入一个菜单对象、一个视图对象和一个菜单信息对象 + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { + // 如果当前的焦点笔记项数据对象不为空,就执行以下操作 + if (mFocusNoteDataItem != null) { + // 设置菜单的标题为焦点笔记项数据对象的摘要 + menu.setHeaderTitle(mFocusNoteDataItem.getSnippet()); + // 添加三个菜单项,分别是查看文件夹、删除文件夹和修改文件夹名称,并设置其ID和标题 + menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view); + menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete); + menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name); + } + } + }; + + @Override + // 这个方法是在上下文菜单关闭时调用的,传入一个菜单对象 + public void onContextMenuClosed(Menu menu) { + // 如果列表视图对象不为空,就设置其创建上下文菜单的监听器为null + if (mNotesListView != null) { + mNotesListView.setOnCreateContextMenuListener(null); + } + // 调用父类的方法 + super.onContextMenuClosed(menu); + } + @Override + + // 这个方法是在选择上下文菜单中的某一项时调用的,传入一个菜单项对象 + public boolean onContextItemSelected(MenuItem item) { + // 如果当前的焦点笔记项数据对象为空,就打印错误日志,并返回false + if (mFocusNoteDataItem == null) { + Log.e(TAG, "The long click data item is null"); + return false; + } + // 根据菜单项的ID,执行相应的操作 + switch (item.getItemId()) { + // 如果是查看文件夹菜单项,就调用打开文件夹的方法,传入焦点笔记项数据对象 + case MENU_FOLDER_VIEW: + openFolder(mFocusNoteDataItem); + break; + // 如果是删除文件夹菜单项,就弹出一个确认对话框,询问用户是否要删除该文件夹 + case MENU_FOLDER_DELETE: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(getString(R.string.alert_title_delete)); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(getString(R.string.alert_message_delete_folder)); + // 如果用户点击确定,就调用删除文件夹的方法,传入焦点笔记项数据对象的ID + builder.setPositiveButton(android.R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + deleteFolder(mFocusNoteDataItem.getId()); + } + }); + // 如果用户点击取消,就什么都不做 + builder.setNegativeButton(android.R.string.cancel, null); + // 显示对话框 + builder.show(); + break; + // 如果是修改文件夹名称菜单项,就调用显示创建或修改文件夹对话框的方法,传入false表示不是创建 + case MENU_FOLDER_CHANGE_NAME: + showCreateOrModifyFolderDialog(false); + break; + // 如果是其他菜单项,就什么都不做 + default: + break; + } + + // 返回true表示处理了该事件 + return true; + } + + @Override + // 这个方法是在准备选项菜单时调用的,传入一个菜单对象 + public boolean onPrepareOptionsMenu(Menu menu) { + // 清空菜单对象中的所有菜单项 + menu.clear(); + // 根据当前的列表编辑状态,执行相应的操作 + if (mState == ListEditState.NOTE_LIST) { + // 如果是笔记列表状态,就从资源文件中加载笔记列表菜单,并设置同步或取消同步菜单项的标题 + getMenuInflater().inflate(R.menu.note_list, menu); + // set sync or sync_cancel + menu.findItem(R.id.menu_sync).setTitle( + GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync); + } else if (mState == ListEditState.SUB_FOLDER) { + // 如果是子文件夹状态,就从资源文件中加载子文件夹菜单 + getMenuInflater().inflate(R.menu.sub_folder, menu); + } else if (mState == ListEditState.CALL_RECORD_FOLDER) { + // 如果是通话记录文件夹状态,就从资源文件中加载通话记录文件夹菜单 + getMenuInflater().inflate(R.menu.call_record_folder, menu); + } else { + // 如果是其他状态,就打印错误日志 + Log.e(TAG, "Wrong state:" + mState); + } + // 返回true表示准备好了选项菜单 + return true; + } + + @Override + // 这个方法是在选择选项菜单中的某一项时调用的,传入一个菜单项对象 + public boolean onOptionsItemSelected(MenuItem item) { + // 根据菜单项的ID,执行相应的操作 + switch (item.getItemId()) { + // 如果是新建文件夹菜单项,就调用显示创建或修改文件夹对话框的方法,传入true表示是创建 + case R.id.menu_new_folder: { + showCreateOrModifyFolderDialog(true); + break; + } + // 如果是导出文本菜单项,就调用导出笔记到文本的方法 + case R.id.menu_export_text: { + exportNoteToText(); + break; + } + // 如果是同步或取消同步菜单项,就判断是否是同步模式 + case R.id.menu_sync: { + if (isSyncMode()) { + // 如果是同步模式,就判断菜单项的标题是否是同步,如果是,就调用同步服务类的方法,开始同步 + if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) { + GTaskSyncService.startSync(this); + } else { + // 否则,就调用同步服务类的方法,取消同步 + GTaskSyncService.cancelSync(this); + } + } else { + // 如果不是同步模式,就调用启动偏好设置Activity的方法 + startPreferenceActivity(); + } + break; + } + // 如果是设置菜单项,就调用启动偏好设置Activity的方法 + case R.id.menu_setting: { + startPreferenceActivity(); + break; + } + // 如果是新建笔记菜单项,就调用创建新笔记的方法 + case R.id.menu_new_note: { + createNewNote(); + break; + } + // 如果是搜索菜单项,就调用启动搜索请求的方法 + case R.id.menu_search: + onSearchRequested(); + break; + // 如果是其他菜单项,就什么都不做 + default: + break; + } + // 返回true表示处理了该事件 + return true; + } + + @Override + public boolean onSearchRequested() { + startSearch(null, false, null /* appData */, false); + return true; + } + + private void exportNoteToText() { + final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this); + new AsyncTask() { + + @Override + protected Integer doInBackground(Void... unused) { + return backup.exportToText(); + } + + @Override + // 这个方法是在异步任务执行完毕后调用的 + protected void onPostExecute(Integer result) { + // 根据结果的不同,显示不同的对话框 + if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) { + // 如果结果是SD卡未挂载,就创建一个警告对话框 + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + // 设置对话框的标题为导出失败 + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + // 设置对话框的内容为SD卡未挂载的错误信息 + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_unmounted)); + // 设置对话框的确定按钮,点击后关闭对话框 + builder.setPositiveButton(android.R.string.ok, null); + // 显示对话框 + builder.show(); + } else if (result == BackupUtils.STATE_SUCCESS) { + // 如果结果是成功,就创建一个提示对话框 + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + // 设置对话框的标题为导出成功 + builder.setTitle(NotesListActivity.this + .getString(R.string.success_sdcard_export)); + // 设置对话框的内容为导出文件的位置和名称 + builder.setMessage(NotesListActivity.this.getString( + R.string.format_exported_file_location, backup + .getExportedTextFileName(), backup.getExportedTextFileDir())); + // 设置对话框的确定按钮,点击后关闭对话框 + builder.setPositiveButton(android.R.string.ok, null); + // 显示对话框 + builder.show(); + } else if (result == BackupUtils.STATE_SYSTEM_ERROR) { + // 如果结果是系统错误,就创建一个警告对话框 + AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this); + // 设置对话框的标题为导出失败 + builder.setTitle(NotesListActivity.this + .getString(R.string.failed_sdcard_export)); + // 设置对话框的内容为系统错误的信息 + builder.setMessage(NotesListActivity.this + .getString(R.string.error_sdcard_export)); + // 设置对话框的确定按钮,点击后关闭对话框 + builder.setPositiveButton(android.R.string.ok, null); + // 显示对话框 + builder.show(); + } + } + +// 执行异步任务 + }.execute(); + } + + private boolean isSyncMode() { + return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0; + } + + private void startPreferenceActivity() { + Activity from = getParent() != null ? getParent() : this; + Intent intent = new Intent(from, NotesPreferenceActivity.class); + from.startActivityIfNeeded(intent, -1); + } + + // 这个内部类实现了列表项点击监听器的接口,用来处理列表视图中的点击事件 + private class OnListItemClickListener implements OnItemClickListener { + + // 这个方法是在点击列表视图中的某一项时调用的,传入一个父视图对象、一个被点击的视图对象、一个位置和一个ID + public void onItemClick(AdapterView parent, View view, int position, long id) { + // 如果被点击的视图对象是一个笔记列表项对象,就执行以下操作 + if (view instanceof NotesListItem) { + // 获取笔记列表项对象中的笔记项数据对象 + NoteItemData item = ((NotesListItem) view).getItemData(); + // 判断列表适配器是否处于选择模式 + if (mNotesListAdapter.isInChoiceMode()) { + // 如果是选择模式,并且笔记项数据对象的类型是笔记类型,就执行以下操作 + if (item.getType() == Notes.TYPE_NOTE) { + // 计算出被点击的位置(减去列表视图的头部视图数量),并调用操作模式回调对象的方法,改变该位置的选中状态 + position = position - mNotesListView.getHeaderViewsCount(); + mModeCallBack.onItemCheckedStateChanged(null, position, id, + !mNotesListAdapter.isSelectedItem(position)); + } + // 返回,不执行后面的操作 + return; + } + + // 根据当前的列表编辑状态,执行相应的操作 + switch (mState) { + // 如果是笔记列表状态,就判断笔记项数据对象的类型 + case NOTE_LIST: + // 如果是文件夹类型或系统类型,就调用打开文件夹的方法,传入笔记项数据对象 + if (item.getType() == Notes.TYPE_FOLDER + || item.getType() == Notes.TYPE_SYSTEM) { + openFolder(item); + } else if (item.getType() == Notes.TYPE_NOTE) { + // 如果是笔记类型,就调用打开笔记节点的方法,传入笔记项数据对象 + openNode(item); + } else { + // 如果是其他类型,就打印错误日志 + Log.e(TAG, "Wrong note type in NOTE_LIST"); + } + break; + // 如果是子文件夹状态或通话记录文件夹状态,就判断笔记项数据对象的类型 + case SUB_FOLDER: + case CALL_RECORD_FOLDER: + // 如果是笔记类型,就调用打开笔记节点的方法,传入笔记项数据对象 + if (item.getType() == Notes.TYPE_NOTE) { + openNode(item); + } else { + // 如果是其他类型,就打印错误日志 + Log.e(TAG, "Wrong note type in SUB_FOLDER"); + } + break; + // 如果是其他状态,就什么都不做 + default: + break; + } + } + } + + } + + // 这个方法是开始查询目标文件夹的 + private void startQueryDestinationFolders() { + // 设置查询条件,筛选出类型为文件夹,并且父ID不是回收站文件夹,并且ID不是当前文件夹的笔记项 + String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?"; + // 如果当前的列表编辑状态是笔记列表状态,就保持原来的查询条件,否则就加上根文件夹的ID + selection = (mState == ListEditState.NOTE_LIST) ? selection: + "(" + selection + ") OR (" + NoteColumns.ID + "=" + Notes.ID_ROOT_FOLDER + ")"; + + // 调用后台查询处理器对象,开始查询笔记的数据,并指定查询标识符、投影、条件和排序方式 + mBackgroundQueryHandler.startQuery(FOLDER_LIST_QUERY_TOKEN, + null, + Notes.CONTENT_NOTE_URI, + FoldersListAdapter.PROJECTION, + selection, + new String[] { + String.valueOf(Notes.TYPE_FOLDER), + String.valueOf(Notes.ID_TRASH_FOLER), + String.valueOf(mCurrentFolderId) + }, + NoteColumns.MODIFIED_DATE + " DESC"); + } + + // 这个方法是实现列表项长按监听器的接口,用来处理列表视图中的长按事件 + public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { + // 如果被长按的视图对象是一个笔记列表项对象,就执行以下操作 + if (view instanceof NotesListItem) { + // 获取笔记列表项对象中的笔记项数据对象,并赋值给当前的焦点笔记项数据对象 + mFocusNoteDataItem = ((NotesListItem) view).getItemData(); + // 判断焦点笔记项数据对象的类型是否是笔记类型,并且列表适配器是否不处于选择模式 + if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) { + // 如果是,就调用列表视图对象的方法,启动操作模式,并传入操作模式回调对象 + if (mNotesListView.startActionMode(mModeCallBack) != null) { + // 如果启动成功,就调用操作模式回调对象的方法,改变被长按位置的选中状态,并执行触觉反馈 + mModeCallBack.onItemCheckedStateChanged(null, position, id, true); + mNotesListView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } else { + // 如果启动失败,就打印错误日志 + Log.e(TAG, "startActionMode fails"); + } + } else if (mFocusNoteDataItem.getType() == Notes.TYPE_FOLDER) { + // 如果焦点笔记项数据对象的类型是文件夹类型,就设置列表视图对象的创建上下文菜单的监听器为文件夹创建上下文菜单的监听器 + mNotesListView.setOnCreateContextMenuListener(mFolderOnCreateContextMenuListener); + } + } + // 返回false表示没有处理该事件 + return false; + } +} diff --git a/doc/精读报告/widget/NoteWidgetProvider.doc b/doc/精读报告/widget/NoteWidgetProvider.doc new file mode 100644 index 0000000..364842f --- /dev/null +++ b/doc/精读报告/widget/NoteWidgetProvider.doc @@ -0,0 +1,169 @@ +/* + * 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.widget; +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.util.Log; +import android.widget.RemoteViews; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.data.Notes.NoteColumns; +import net.micode.notes.tool.ResourceParser; +import net.micode.notes.ui.NoteEditActivity; +import net.micode.notes.ui.NotesListActivity; + +public abstract class NoteWidgetProvider extends AppWidgetProvider { + //查询便签数据库时使用的列名 + public static final String [] PROJECTION = new String [] { + NoteColumns.ID, + NoteColumns.BG_COLOR_ID, + NoteColumns.SNIPPET + }; + + //PROJECTION中对应列的下标 + public static final int COLUMN_ID = 0; + public static final int COLUMN_BG_COLOR_ID = 1; + public static final int COLUMN_SNIPPET = 2; + + //Log输出的标签 + private static final String TAG = "NoteWidgetProvider"; + + /* + * 重写onDeleted()方法,实现删除 Widget 时清除相应 Widget 对应的便签数据库中的记录 + * value:用于更新的ContentValues,将 Widget ID 设为无效值 + * appWidgetIds:被删除的所有 Widget 的 ID 数组 + */ + @Override +// 定义一个方法,用于在widget被删除时更新数据库中的widget_id字段 + public void onDeleted(Context context, int[] appWidgetIds) { + // 创建一个ContentValues对象,用于存放要更新的字段和值 + ContentValues values = new ContentValues(); + // 把widget_id设置为无效的值 + values.put(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + //遍历所有被删除的widget的id + for (int i = 0; i < appWidgetIds.length; i++) { + // 根据widget_id更新数据库中对应的笔记记录 + context.getContentResolver().update(Notes.CONTENT_NOTE_URI, + values, + NoteColumns.WIDGET_ID + "=?", + new String[] { String.valueOf(appWidgetIds[i])}); + } + } + +// 定义一个方法,用于根据widget_id查询数据库中的笔记信息 + private Cursor getNoteWidgetInfo(Context context, int widgetId) { + // 使用ContentResolver查询笔记表,返回一个Cursor对象 + return context.getContentResolver().query(Notes.CONTENT_NOTE_URI, + PROJECTION, + NoteColumns.WIDGET_ID + "=? AND " + NoteColumns.PARENT_ID + "<>?", + new String[] { String.valueOf(widgetId), String.valueOf(Notes.ID_TRASH_FOLER) }, + null); + } + +// 定义一个方法,用于更新widget的视图 + protected void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用另一个重载的update方法,传入false表示不是访客模式 + update(context, appWidgetManager, appWidgetIds, false); + } + private void update(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds, + boolean privacyMode) { + for (int i = 0; i < appWidgetIds.length; i++) { + if (appWidgetIds[i] != AppWidgetManager.INVALID_APPWIDGET_ID) { + // 获取 Widget 的默认背景 ID + int bgId = ResourceParser.getDefaultBgId(context); + // 默认便签摘要为空字符串 + String snippet = ""; + // 创建用于启动编辑页面的 Intent,并添加必要的参数 + Intent intent = new Intent(context, NoteEditActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_ID, appWidgetIds[i]); + intent.putExtra(Notes.INTENT_EXTRA_WIDGET_TYPE, getWidgetType()); + + // 从数据库中查询指定 Widget ID 对应的便签信息 + Cursor c = getNoteWidgetInfo(context, appWidgetIds[i]); + if (c != null && c.moveToFirst()) { + // 检查查询结果是否出现异常,如出现异常则打印错误日志和异常信息 + if (c.getCount() > 1) { + Log.e(TAG, "Multiple message with same widget id:" + appWidgetIds[i]); + c.close(); + return; + } + // 设置 Widget 中需要显示的便签摘要、背景 ID、绑定的便签 ID 和点击跳转功能 + snippet = c.getString(COLUMN_SNIPPET); + bgId = c.getInt(COLUMN_BG_COLOR_ID); + intent.putExtra(Intent.EXTRA_UID, c.getLong(COLUMN_ID)); + intent.setAction(Intent.ACTION_VIEW); + } else { + // 若查询结果为空,则打开编辑页面并设置其模式为插入模式 + snippet = context.getResources().getString(R.string.widget_havenot_content); + intent.setAction(Intent.ACTION_INSERT_OR_EDIT); + } + + // 关闭查询结果的 Cursor 对象 + if (c != null) { + c.close(); + } + + // 创建 RemoteViews 对象,并为其设置相应布局及需要显示的参数 + RemoteViews rv = new RemoteViews(context.getPackageName(), getLayoutId()); + rv.setImageViewResource(R.id.widget_bg_image, getBgResourceId(bgId)); + intent.putExtra(Notes.INTENT_EXTRA_BACKGROUND_ID, bgId); + + /** + * Generate the pending intent to start host for the widget + */ + // 定义一个变量pendingIntent,初始化为null + PendingIntent pendingIntent = null; +// 如果privacyMode为真,表示用户处于访客模式 + if (privacyMode) { + // 设置widget_text的文本为“访客模式” + rv.setTextViewText(R.id.widget_text, + context.getString(R.string.widget_under_visit_mode)); + // 创建一个PendingIntent,用于启动NotesListActivity + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], new Intent( + context, NotesListActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + } else { + // 否则,设置widget_text的文本为snippet,即笔记的摘要 + rv.setTextViewText(R.id.widget_text, snippet); + // 创建一个PendingIntent,用于启动intent指定的Activity + pendingIntent = PendingIntent.getActivity(context, appWidgetIds[i], intent, + PendingIntent.FLAG_UPDATE_CURRENT); + } + +// 设置widget_text的点击事件为pendingIntent + rv.setOnClickPendingIntent(R.id.widget_text, pendingIntent); +// 更新widget的视图 + appWidgetManager.updateAppWidget(appWidgetIds[i], rv); + } + } + } + +// 定义一个抽象方法,用于根据bgId返回背景资源的id + protected abstract int getBgResourceId(int bgId); + +// 定义一个抽象方法,用于返回布局资源的id + protected abstract int getLayoutId(); + +// 定义一个抽象方法,用于返回widget的类型 + protected abstract int getWidgetType(); +} diff --git a/doc/精读报告/widget/NoteWidgetProvider_2x.doc b/doc/精读报告/widget/NoteWidgetProvider_2x.doc new file mode 100644 index 0000000..9933e13 --- /dev/null +++ b/doc/精读报告/widget/NoteWidgetProvider_2x.doc @@ -0,0 +1,48 @@ +/* + * 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.widget; //声明package + +import android.appwidget.AppWidgetManager; //引用类 +import android.content.Context; //引用类 + +import net.micode.notes.R; //引用类 +import net.micode.notes.data.Notes; //引用类 +import net.micode.notes.tool.ResourceParser; //引用类 + +public class NoteWidgetProvider_2x extends NoteWidgetProvider {//继承NoteWidgetProvider类 + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + super.update(context, appWidgetManager, appWidgetIds); //调用NoteWidgetProvider的update方法 + } + + @Override + protected int getLayoutId() { //重写NoteWidgetProvider中的getLayoutId方法 + return R.layout.widget_2x; //返回 widget_2x 布局文件的ID + } + + @Override + protected int getBgResourceId(int bgId) { //重写NoteWidgetProvider中的getBgResourceId方法,接受传入的bgId参数 + return ResourceParser.WidgetBgResources.getWidget2xBgResource(bgId); //调用ResourceParser类中的getWidget2xBgResource(bgId)方法,返回该bgId对应的Widget2xBg资源ID + } + + @Override + protected int getWidgetType() { //重写NoteWidgetProvider中的getWidgetType方法 + return Notes.TYPE_WIDGET_2X; //返回Note中的TYPE_WIDGET_2X常量值 + } +} + diff --git a/doc/精读报告/widget/NoteWidgetProvider_4x.doc b/doc/精读报告/widget/NoteWidgetProvider_4x.doc new file mode 100644 index 0000000..17222a0 --- /dev/null +++ b/doc/精读报告/widget/NoteWidgetProvider_4x.doc @@ -0,0 +1,58 @@ +/* + * 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.widget; + +import android.appwidget.AppWidgetManager; +import android.content.Context; + +import net.micode.notes.R; +import net.micode.notes.data.Notes; +import net.micode.notes.tool.ResourceParser; + + +public class NoteWidgetProvider_4x extends NoteWidgetProvider { + + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + // 调用父类中的 update 方法,进行具体的 Widget 内容更新操作 + super.update(context, appWidgetManager, appWidgetIds); + } + + + protected int getLayoutId() { + return R.layout.widget_4x; + } + + /** + * 根据传入的背景颜色 ID 获取对应的背景资源 ID + * @param bgId 背景颜色 ID + * @return 对应的背景资源 ID + */ + @Override + protected int getBgResourceId(int bgId) { + return ResourceParser.WidgetBgResources.getWidget4xBgResource(bgId); + } + + /** + * 获取该 Widget 对应的类型常量,用于在程序中进行判断和处理 + * @return 4x4 Widget 对应的类型常量 + */ + @Override + protected int getWidgetType() { + return Notes.TYPE_WIDGET_4X; + } +} From 69ef45c5eae48ba7bf503c6eb1cbc783a9fc0762 Mon Sep 17 00:00:00 2001 From: pj36foInf <445038096@qq.com> Date: Thu, 20 Apr 2023 21:47:13 +0800 Subject: [PATCH 3/8] 4/20 --- NUNG95)KSCVJKJJAANMGS(8.png | Bin 0 -> 23775 bytes W3~]OT3)~ZILZ1W`2_1M`R4.png | Bin 0 -> 23838 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 NUNG95)KSCVJKJJAANMGS(8.png create mode 100644 W3~]OT3)~ZILZ1W`2_1M`R4.png diff --git a/NUNG95)KSCVJKJJAANMGS(8.png b/NUNG95)KSCVJKJJAANMGS(8.png new file mode 100644 index 0000000000000000000000000000000000000000..78adfc7937dad1f3c6a5844b88043f1aba744031 GIT binary patch literal 23775 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 literal 0 HcmV?d00001 From eb91a71f154646e4c19ef213b269ee292e6d6aba Mon Sep 17 00:00:00 2001 From: pj36foInf <445038096@qq.com> Date: Fri, 28 Apr 2023 16:53:11 +0800 Subject: [PATCH 4/8] 4/28 --- .../物理体系结构体.png | Bin 0 -> 11371 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/显示实时天气/物理体系结构体.png diff --git a/doc/显示实时天气/物理体系结构体.png b/doc/显示实时天气/物理体系结构体.png new file mode 100644 index 0000000000000000000000000000000000000000..8d353ab97c41ff22be6b5fdfaca765ceda5c22b3 GIT binary patch literal 11371 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 KcZxJ0J^vr)Qb{@h literal 0 HcmV?d00001 From 8899bbe28896c194a21787b9ec1d92a78e3c0d36 Mon Sep 17 00:00:00 2001 From: pj36foInf <445038096@qq.com> Date: Fri, 28 Apr 2023 16:53:40 +0800 Subject: [PATCH 5/8] 4/28 --- doc/字符统计/物理体系结构图.png | Bin 0 -> 16772 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/字符统计/物理体系结构图.png diff --git a/doc/字符统计/物理体系结构图.png b/doc/字符统计/物理体系结构图.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf1bc7811a1289415ad57b5ec79d21964c49c54 GIT binary patch literal 16772 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 literal 0 HcmV?d00001 From c0add4df1c525d302296296ac897b024ee4bb750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E5=BF=97=E5=8F=91?= <3083973277@qq.com> Date: Fri, 12 May 2023 15:17:52 +0800 Subject: [PATCH 6/8] 5.12 --- doc/泛读报告.docx | Bin 526508 -> 527869 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/泛读报告.docx b/doc/泛读报告.docx index 39bb0ade3a79a87f747352c1fc0ba9e688e9b71f..016d375f996a5ad6b014849a6fc9516922b5f326 100644 GIT binary patch delta 23340 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�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 cG$H|{pf+F%2_O!A4)&7(+=$6b Date: Fri, 12 May 2023 15:19:15 +0800 Subject: [PATCH 7/8] 5.12 --- doc/~$泛读报告.docx | Bin 0 -> 162 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/~$泛读报告.docx diff --git a/doc/~$泛读报告.docx b/doc/~$泛读报告.docx new file mode 100644 index 0000000000000000000000000000000000000000..07e655a5e86eb1f7348f6e379fc79d0992c2b336 GIT binary patch literal 162 gcmZRzFf%kYVjvN)GFUK}F&HwKGLWp5M4K2G01-R_7XSbN literal 0 HcmV?d00001 From 5c169c3ad3af013ac075a112d031e0dd7eaf0f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E5=BF=97=E5=8F=91?= <3083973277@qq.com> Date: Fri, 12 May 2023 15:33:45 +0800 Subject: [PATCH 8/8] 5.12 --- doc/~$泛读报告.docx | Bin 162 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 doc/~$泛读报告.docx diff --git a/doc/~$泛读报告.docx b/doc/~$泛读报告.docx deleted file mode 100644 index 07e655a5e86eb1f7348f6e379fc79d0992c2b336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162 gcmZRzFf%kYVjvN)GFUK}F&HwKGLWp5M4K2G01-R_7XSbN