前言
本文的內(nèi)容主要是解析Ridder Note APP 的制作流程唆垃,以及代碼的具體實(shí)現(xiàn),若有什么不足之處写妥,還請(qǐng)?zhí)岢鼋ㄗh鸳粉,附上這個(gè) APP 的 Github 地址 Ridder Note 歡迎大家 star 和 fork.
Ridder Note可實(shí)現(xiàn)功能:
[note的增刪改查]
[note分享到QQ WECHAT]
[note備份到服務(wù)器]
本文的主要內(nèi)容
- 查詢note的實(shí)現(xiàn)(litepal+sqlite)
- StarNote和 UnStarNote切換的實(shí)現(xiàn)(Broadcast)
- 備份日記到服務(wù)器的實(shí)現(xiàn)(接口回調(diào) +handler)
先來(lái)一波Note的展示吧,這款 APP 還是非常精美和優(yōu)雅的
- 增刪查改note的效果
-
StarNote和 UnStarNote切換 上翻下翻記事 清空記事后服務(wù)器端恢復(fù)記事的效果
2.gif
一集畅、日記查詢的實(shí)現(xiàn)
1近弟、利用litepal建立表
LitePal是一款開源的Android數(shù)據(jù)庫(kù)框架,采用對(duì)象關(guān)系映射(ORM)模式挺智,將常用的數(shù)據(jù)庫(kù)功能進(jìn)行封裝祷愉,可以不用寫一行SQL語(yǔ)句就可以完成創(chuàng)建表、增刪改查的操作。
相關(guān)教程可以參見(jiàn)鏈接litepal
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="Note"></dbname>
<version value="1"></version>
<list>
<mapping class="com.tomridder.ridder_note.bean.Note"></mapping>
</list>
</litepal>
litePal增刪改已經(jīng)非常簡(jiǎn)單了二鳄,這里就介紹下最復(fù)雜的查詢赴涵。
2、按關(guān)鍵字查詢note的實(shí)現(xiàn)
String key=starEtSearch.getText().toString();
notes=querylikeStarNotes(key);
recycleViewStarNoteAdapter =new RecycleViewStarNoteAdapter(R.layout.star_note,notes);
recycleViewStarNoteAdapter.setOnItemChildClickListener(StarNoteFragment.this);
starNotesRecyclerView.setAdapter(recycleViewStarNoteAdapter);
private List<Note> querylikeStarNotes(String key)
{
List<Note> notes=DataSupport.where("(title like ? or content like ?) and star = ? ","%"+key+"%","%"+key+"%",1+"").find(Note.class);
Log.i("note","note size = "+ notes.size());
return notes;
}
在querylikeStarNotes函數(shù)中查詢title content中包含字符串key的notes订讼,再傳給recycleViewStarNoteAdapter髓窜,starNotesRecyclerView重新setAdapter。
3欺殿、上翻下翻查詢note
Note note=getTheNextUnStarNote(oldNote);
noteShowTitle.setText(note.getTitle());
noteShowContent.setText(note.getContent());
noteShowTime.setText(DateFormat.format("MM-dd HH:mm:ss",note.getDate()).toString());
oldNote=note;
public static Note getTheNextUnStarNote(Note oldNote)
{
Note note;
Cursor c= DataSupport.findBySQL("select * from Note " +
"where star =?",String.valueOf(oldNote.getStar()));
while(c.moveToNext())
{
Log.i("note","title ="+oldNote.getTitle()+"content ="+oldNote.getContent()+"date ="+String.valueOf(oldNote.getDate())+
"star = "+String.valueOf(oldNote.getStar()));
String title2=c.getString(c.getColumnIndex("title"));
String content2=c.getString(c.getColumnIndex("content"));
if(title2.equals(oldNote.getTitle())&&content2.equals(oldNote.getContent()))
{
break;
}
}
if( c.moveToNext()==true)
{
String title2 = c.getString(c.getColumnIndex("title"));
String content2 = c.getString(c.getColumnIndex("content"));
long date2 = c.getLong(c.getColumnIndex("date"));
int star2 = c.getInt(c.getColumnIndex("star"));
note = new Note(title2, content2, date2, star2);
Log.i("note","moveToPrevious"+"title ="+note.getTitle()+"content ="+note.getContent()+"date ="+String.valueOf(note.getDate())+
"star = "+String.valueOf(note.getStar()));
}
else
{
c.moveToFirst();
String title2 = c.getString(c.getColumnIndex("title"));
String content2 = c.getString(c.getColumnIndex("content"));
long date2 = c.getLong(c.getColumnIndex("date"));
int star2 = c.getInt(c.getColumnIndex("star"));
note = new Note(title2, content2, date2, star2);
Log.i("note","moveToLast"+"title ="+note.getTitle()+"content ="+note.getContent()+"date ="+String.valueOf(note.getDate())+
"star = "+String.valueOf(note.getStar()));
}
return note;
}
litePal沒(méi)有查詢上一條數(shù)據(jù)的API寄纵,所以這里還是用了sqlite。
getTheNextUnStarNote函數(shù)中用while循環(huán)定位到當(dāng)前note所在的游標(biāo)位置脖苏,找到后跳出循環(huán)程拭。
接著游標(biāo)下移一位,返回所在位置的note帆阳。如果當(dāng)前游標(biāo)已經(jīng)在最后一位哺壶,則將游標(biāo)移到第一位,返回note蜒谤。
接著分別setText即可山宾,不要忘了將返回的note賦值給oldNote,用于下次查詢鳍徽。
二资锰、StarNote和 UnStarNote切換的實(shí)現(xiàn)
case R.id.iv_star2:
note=(Note)adapter.getData().get(position);
Note note1=new Note();
note1.setStar(2);
int result1=note1.updateAll("title = ? and content = ? and " +
"date = ? and star = ?",note.getTitle(),note.getContent()
,String.valueOf(note.getDate()),String.valueOf(note.getStar()));
Log.i("note","result1 "+result1);
if(result1>0)
{
recycleViewStarNoteAdapter.remove(position);
}
intent=new Intent("com.tomridder.UnStarNote");
getContext().sendBroadcast(intent);
break;
class UnStarChangeReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
List<Note> unStarNotes=QueryUnStarNotes();
recycleViewUnStarNoteAdapter =new RecycleViewUnStarNoteAdapter(R.layout.unstar_note,unStarNotes);
recycleViewUnStarNoteAdapter.setOnItemChildClickListener(UnStarNoteFragment.this);
unStarNotesRecyclerView.setAdapter(recycleViewUnStarNoteAdapter);
}
}
在從StarNote到UnStarNote的轉(zhuǎn)換中,首先在數(shù)據(jù)庫(kù)中更改star的值從1到2阶祭。
如果更改成功從當(dāng)前的StarNoteFragment中的recycleView中移除當(dāng)前的note绷杜。
接著發(fā)出一條名字為"com.tomridder.UnStarNote"的廣播。
UnStarFragment中會(huì)注冊(cè)這條廣播濒募,如果接收到則會(huì)刷新UnStarNoteFragment的recycleView鞭盟。從而完成整個(gè)效果。
三瑰剃、備份日記到服務(wù)器的實(shí)現(xiàn)
1齿诉、更改日記同步到服務(wù)器端的實(shí)現(xiàn)
final String SERVER_URL="http://coder.struggling-bird.cn:8761/weixin/note/update?";
final String data="title="+title+"&date="+longToString(System.currentTimeMillis())+"&content="+content+"&star="+oldNote.getStar()
+"&oldTitle="+oldNote.getTitle()+"&oldDate="+longToString(oldNote.getDate())+"&oldContent="+oldNote.getContent()
+"&oldStar="+oldNote.getStar();
new Thread()
{
@Override
public void run() {
super.run();
OkHttpClient okHttpClient=new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.build();
Request request=new Request.Builder()
.url(SERVER_URL+data)
.build();
try
{
Response response=okHttpClient.newCall(request).execute();
if(response.isSuccessful())
{
Log.i("Note",response.body().toString());
}else
{
Log.i("Note","failed");
}
}catch (IOException e)
{
e.printStackTrace();
}
}
}.start();
這里只需要用使用okhttp,將SERVER_URL和參數(shù)data(包含oldNote的 title,content,date,star的newNote的title,content,date,star )拼接起來(lái)晌姚,
作為Request的url參數(shù)粤剧,最后發(fā)起請(qǐng)求即可。
2挥唠、 從服務(wù)器端恢復(fù)日記到本地的實(shí)現(xiàn)
public static void ParseDataWithJsonObject(String response)
{
try
{
JSONArray notes=new JSONArray(response);
DataSupport.deleteAll(Note.class);
for(int i=0;i<notes.length();i++)
{
JSONObject note=notes.getJSONObject(i);
String title=note.getString("title");
String content=note.getString("content");
String date=note.getString("date");
int star=note.getInt("star");
Note note1=new Note(title,content,stringToLong(date),star);
note1.save();
}
}catch (JSONException e)
{
e.printStackTrace();
}
}
new Thread()
{
@Override
public void run() {
super.run();
OkHttpClient okHttpClient=new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.build();
Request request=new Request.Builder()
.url(SERVER_URL)
.build();
try
{
Response response=okHttpClient.newCall(request).execute();
if(response.isSuccessful())
{
String data=response.body().string();
ParseDataWithJsonObject(data);
Intent intent=new Intent("com.tomridder.StarNote");
sendBroadcast(intent);
Intent intent2=new Intent("com.tomridder.UnStarNote");
sendBroadcast(intent2);
}
}catch (IOException e)
{
e.printStackTrace();
}
}
}.start();
首先向SERVER_URL發(fā)起請(qǐng)求抵恋,得到response后,在ParseDataWithJsonObject中將resposne的JSON串轉(zhuǎn)成jsonArray宝磨,
接著利用for循環(huán)取出jsonArray中的jsonObject弧关,轉(zhuǎn)換成note對(duì)象盅安,一個(gè)個(gè)寫到數(shù)據(jù)庫(kù)中。
public interface Callback1
{
void fresh();
}
Handler handler=new Handler()
{
@Override
public void handleMessage(Message msg)
{
switch (msg.what)
{
case 1:
List<Note> unStarNotes=QueryUnStarNotes();
recycleViewUnStarNoteAdapter =new RecycleViewUnStarNoteAdapter(R.layout.unstar_note,unStarNotes);
recycleViewUnStarNoteAdapter.setOnItemChildClickListener(UnStarNoteFragment.this);
unStarNotesRecyclerView.setAdapter(recycleViewUnStarNoteAdapter);
Log.i("Note","Received Un");
break;
}
}
};
@Override
public void fresh() {
Message message=new Message();
message.what=1;
handler.sendMessage(message);
Log.i("Note","Send Un ");
}
接下來(lái)MainNote Activity和 UnStarFragment 梯醒, StarFragment的通信方式我采取了接口回調(diào)的方式宽堆。
MainNote含有Callback對(duì)象的List集合,UnStarFragment 茸习, StarFragment分別集成自Callback接口畜隶,并實(shí)現(xiàn)fresh()方法。
最后由于不能在子線程 函數(shù)fresh()中刷新recyclerView号胚,我采用了handler來(lái)更改view籽慢。
這樣最后效果實(shí)現(xiàn)。
以上便是我寫這個(gè) APP 的具體實(shí)現(xiàn)思路猫胁,以及踩過(guò)的一些坑箱亿,記錄下來(lái),給大家看看弃秆,最后附上這個(gè) APP 的 Github 地址 Ridder Note 歡迎大家 star 和 fork届惋,如果有什么想法或者建議,非常歡迎大家來(lái)討論