猫窝

在自己窝里折腾点东西


  • 首页

  • 分类

  • 归档

  • 标签

  • 导航

  • 书单

  • 公益

  • 搜索
close

周末是我计划的杀手

发表于 2016-01-16   |   分类于 杂谈

当我想做点事情的时候,总是会计划每天干些什么。原本我以为平时周末下班之后比较累,回来做这些工作之外的事情比较难,而周末时间相对比较宽裕,执行计划应该会比较简单。可实际上却相反,每次周末执行起来反而比平时还要困难些。不要说周末时间充裕可以多做些事情,有时候连原本的计划都没有很好的完成。

这种现象并不是说最近才有的,早几年的计划都是这样。有时候有些计划,常常因为周末的存在被扼杀。对于这种现象,我现在的解释有两种:

  1. 平时工作,身体与脑力都习惯做事情,周末身体与脑力同样习惯休息。

  2. 周末时间比较充裕,认为拖延拖延也没有关系,结果拖着拖着一天就过去了。

还有什么更深层次的原因或者有什么比较好的方式去解决这个问题是我的一个思考题。

SwipeRefreshLayout程序自动触发

发表于 2016-01-15   |   分类于 Android

关于SwipeRefreshLayout程序自动触发是之前就已经解决的问题,只是当时没有记录的习惯,所以没有记录。今天工作主要是针对之前的项目一些修改,并没有新的知识点获得,就拿这个已经获得的东西来滥竽充数。

SwipeRefreshLayout是google自己推出的下拉刷新控件,易用,我在项目中一般都会使用该控件。下面开始说说它的几个常用方法以及相关代码片段。

  • setColorSchemeResources设置用于进度条动画的颜色
1
2
3
4
// 这样设置后,在请求数据的过程中就有四种颜色可以交替变换
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_light,
android.R.color.holo_red_light, android.R.color.holo_orange_light,
android.R.color.holo_green_light);
  • setOnRefreshListener 为下拉刷新添加一个监听事件
1
2
3
4
5
6
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// do something in background
}
});
  • setRefreshing 通知组件刷新状态已经修改,从而显示或者隐藏进度条,下拉刷新时不能调用此方法
1
2
// 一般在自己获取数据完成后调用
swipeRefreshLayout.setRefreshing(false);
  • post(Runnable action) 用于执行后台程序,如果想自动触发下拉刷新,就需要调用此方法
1
2
3
4
5
6
7
8
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
// 显示设置进度条可见
swipeRefreshLayout.setRefreshing(true);
// do something in background
}
});

关于隐性成本的浅识

发表于 2016-01-14   |   分类于 杂谈

这段时间看见不少大牛的公众号有谈到各种各样的隐形成本,如时间成本、信用成本、决策成本等等其他相关内容。其中时间成本是看到比较多的,也是我现在可以想象的。至于信用成本与决策成本现在还不能好好的体会。

那就来谈谈我对时间成本的一些想法。

在看到的例子中是说你在北上广上班,有些人离公司近,有些人为了省点房租就住的远点,然后来回路上浪费不少时间。

关于这个我想其实不是时间的问题,而是意识的问题。

就拿我刚到上海的来说吧,上班就离要坐很久的时间,我也没有觉得这有什么不好,因为离公司近的房租真的住不起。其次,是我也不知道利用这节约的时间用来干什么,每次下班回去之后都是看连续剧或者动漫。这个时候无论我住在公司多么的近其实意义都不是很大,无非是用来看更多的连续剧与动漫。后来工作慢慢顺手,感觉长时间没有进步,又喜欢上读点书,就感觉有事情可以做,这个时候开始意识到时间还是要好好利用的。每次坐公交的时候,要么是听着歌,看着Kindle上的一些小说,感觉还是很不错的。太挤的时候就用来听听小说,感受一下不同世界的故事。虽然大部分东西都忘记差不多,但是脑中也留下了点种子,在日后会时不时的给自己一点帮助。

最近开始准备积累一些东西,才真正感觉到时间的浪费真的很多,尤其是早上早高峰时,我进16号线车站都要比较长时间。而这段时间是很难做些事情的,除了在脑中想些问题或者听听音乐。最近不喜欢听书或者Kindle电子书,而是喜欢纸质书,所以进车厢尽量去有座位的过道,这样方便阅读。如果此时住的近一点,意义就比较大。

还一个关于时间成本的是说找盗版书籍与盗版软件的,这个我是同意的。不单单是说找这些东西浪费的时间远远多余买一本正版书籍或者软件的时间,还有一点是知识创造者辛辛苦苦写出来的东西或者做出来的东西,总得给一个回报的。如果盗版盛行,好的作品可能就少了。对于盗版书籍曾经下过不少英文版的pdf,基本没有看。现在基本没有下了,想看的书都直接去网店购买,买回来就开始看。

原来在Windows上工作的时候,用微软东西编程的时候,盗版软件真的不少,有各种开发软件与办公软件;后来,我将开发环境换成Ubuntu的时候,盗版软件就没有了,都是些开源的或者免费的软件(如果我现在还去用Windows系统,感觉还是会用盗版软件,系统也会是盗版的,怎么就感觉Windows用盗版就成习惯了呢?是不是太穷的原因!!!?)。

还一个例子是说看视频的时候,买会员去广告的,这个我就持保留意见。我觉得在看视频的时候,看看1分钟的广告有时候也挺好的,看看广告都在做些什么,或者乘机让眼睛歇歇。

综上,关于时间成本的问题,往往是不清楚自己用多余的时间干些什么事情比较好。本质上,应该是不知道提升自己,不知道去学习;等意识到需要为自己充电的时候,是会想着法子去节约时间的。其次还有可能是“穷”,又舍不得花钱,感觉能省点就省点,这个我觉得还是该花的就花吧,尤其是在买书这件事情上,就别犹豫了。

RecyclerView的使用入门

发表于 2016-01-13   |   分类于 Android

不应该放弃学习的,更不应该放弃学习新知识。因为有时候新的知识点能够帮助我们更好的工作,并提高一定的工作效率。对于Android开发来说,RecyclerView就是这么个控件。它能够完成ListView与GridView的功能,而且还可以完成瀑布流的功能,关键是切换起来非常方便。

官网中有段英文说明是说RecyclerView是一个更高级与灵活的ListView版本。能够高效加载大量数据,同时我们还可以灵活的自定义该组件。我这只是简单的翻译,完整的可以参考官方网址(访问需要翻墙的)。

现在说明一下其简单的使用方法,下面将会是些代码片段,具体的看到效果还得自己写代码去看看。这里主要用到的组件有RecyclerView与CardView控件(这个比较简单的,就可以和LinearLayout使用方法差不多),然后依然使用前一篇文章使用的Butter Knife开源库。所以gradle配置文件需要涵盖下面的内容。

1
2
3
4
5
dependencies {
compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:recyclerview-v7:23.1.1'
compile 'com.jakewharton:butterknife:7.0.1'
}

gradle引用完jar包,就可以在项目中正常使用RecyclerView与CardView了,首先在MainActivity对应的layout文件中包含RecyclerView控件。

1
2
3
4
5
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/recycler_view" />

像ListView一样,我们需要为RecyclerView中的container添加一个新的layout文件以及对应的Adapter。其对应的layout文件如下,取名为view_book_intro。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- A CardView that contains a TextView -->
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="4dp">
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/book_intro_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.v7.widget.CardView>
</LinearLayout>

对应的Adapter(我取名是BookIntroAdapter)需要集成RecyclerView.Adapter,然后重写其三个方法,完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class BookIntroAdapter extends RecyclerView.Adapter<BookIntroAdapter.ViewHolder> {
private String[] mDataSet;

public static class ViewHolder extends RecyclerView.ViewHolder {
// 获取到RecyclerView的container下的TextView组件信息
@Bind(R.id.book_intro_title) TextView mTextView;
public ViewHolder(View view) {
super(view);
// 别忘记这句,否则TextView就没有初始化
ButterKnife.bind(this, view);
}
}

public BookIntroAdapter(String[] bookDataSet) {
this.mDataSet = bookDataSet;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate
(R.layout.view_book_intro, parent, false);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
// 这里是为控件赋值
holder.mTextView.setText(mDataSet[position]);
}

@Override
public int getItemCount() {
return mDataSet.length;
}
}

看看这段代码是不是要比实现ListView的Adapter更简单呢?

接下来我们就可以在MainActivity中调用RecyclerView组件,MainActiviy的代码片段如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Bind(R.id.recycler_view) RecyclerView recyclerView;
... // 表示其他代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
...

// 1. 这可以实现ListView的功能
recyclerView.setLayoutManager(new LinearLayoutManager(this));

// 2. 这可以实现GridView功能,其中2表示一行显示两个元素
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));

// 3. 这是瀑布流形式的调用方法,如果想看出效果,可以在初始化字符串时多给几个\n
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2,
StaggeredGridLayoutManager.VERTICAL));

recyclerView.setAdapter(new BookIntroAdapter(new String[]{"Java", "Android", "C#"}));
}

注意:上述代码片段中的1、2、3就是不同呈现方式需要的代码,在实际项目中根据实际情况任意选一个就好。看到这么便利的组件,难道不想试一试嘛?

Butter Knife简介

发表于 2016-01-12   |   分类于 Android

最初写Android项目的时候,也不知道可以用什么开源项目,就跟着《第一行代码》里面写的一些东西开始第一个界面。大量的XML文件,Activity中调用控件的时候,用的是下面的代码。

1
2
3
View view = findViewById(R.id.item);
// 如果是其他控件,还得自己手动转,如TextView,则需要这样写
TextView textView = (TextView) findViewById(R.id.text);

起初也没有感觉这么写有什么不好,虽然有点繁琐,但是将这些初始化的组件,在代码起初申明好变量,然后将所有获取控件的代码放在一个统一的方法中,也就无须管事。后来陆续看别人分享的代码或者开源项目的时候,大多数都使用了Butter Knife这个开源库,它是用注解的方式来完成我们之前的工作,形式如下。

1
@Bind(R.id.text) TextView textView;

就一行也许没有看出什么特别优势,但是如果写的控件比较多,这样写的优势还是很明显的,代码量至少节约点,也比较容易读,好像TextView是@Bind(R.id.text)类型一样(这样理解是不是有点问题)。声明完这些控件之后,不要忘记在Activity中的onCreated方法中调用一行代码,否则会出现空指针异常,找不到控件之类的。

1
2
3
4
5
6
7
8
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 一定要加上这行代码
ButterKnife.bind(this);
// do more things
}

如果不是在Activity中使用这个,在其他地方使用,如继承RecyclerView.ViewHolder的ViewHolder中,绑定方式有些许区别。

1
2
3
4
5
6
7
8
public static class ViewHolder extends RecyclerView.ViewHolder {
@Bind(R.id.text) TextView mTextView;
public ViewHolder(View view) {
super(view);
// 注意这句,绑定方式和之前的是不是有点不一样
ButterKnife.bind(this, view);
}
}

如何在自己的项目中使用ButterKnife开源库,只需要在gradle中配置一行引用依赖

1
compile 'com.jakewharton:butterknife:7.0.1'

这个开源库学习起来还是比较简单的,基本上将其官网的东西从头到尾看一遍就好了,如果忘记就再查一下。我这里只是简单的说明了一下Butter Knife的使用方式,关于它的更多信息,可以参考其官网。

============
2016.01.18补记
今天在用ButterKnife的时候遇到一个错误exception java.lang.RuntimeException: Unable to bind views for Fragment on ButterKnife.bind(this, view)。经过查阅发现是控件绑定错误,本来是ImageView控件,在使用ButterKnife进行绑定的时候使用了Button。参考Stackoverflow网站

博客不好写

发表于 2016-01-11   |   分类于 杂谈

每次自己买书看的时候,从来没有想过这些文字写出来到底有困难,读起来倒是无比顺畅。每天看着微信公众号写的文章,同样让人感觉没有什么困难。最近这段时间尝试着自己写点东西,无论是技术相关的还是非技术相关的,感觉都很难将一句话写的明白。每每改了好几回,也没觉得句子是通畅的。可有想不出更加好的句子,最后也就勉为其难的发表出来,好在这些主要是写给自己看的,文笔差点就差点了。

句子反反复复的写不顺畅是博客不好写的一个原因,其次还有一个原因是不知道写些什么。无论是技术方面,还是非技术方面,没开始写的时候,想到应该这么写来着。等到真开始写的时候,又不知道如何下手,或者记得怎么下手的时候,就又觉得这样写不是很好,于是又迟迟的无法敲动键盘。只能眼睁睁的看着自己的markdown编辑器想着我该写些什么。

对于技术文章无法下手,我大致想出的原因是我总想着写出一系列惊人的技术分享。可无奈自己所遇到的问题与技术都是写小问题,想清楚原因或者看清楚日志,再借助一下Google,就能解决问题。问题最终解决,也没觉得有什么,就认为这些没什么好记录的,想写一篇质量更高的技术文章,而这个感觉就更困难。这无形中就造成“高不成低不就的感觉”。

关于非技术文章,就前面写的那几篇来说,基本就是自己的一些经历和个人感想,属于自己脑子中的东西,想到了就写出来,也不管到底值不值得写。写着写着,总感觉这种写法有点无病呻吟的感觉,写出来的东西似乎没有什么参考性。总感觉文章写出来有点过于干涸,没什么养分,让人无法一直这么写下去。后面想着再写点东西的时候,一看又是这种模式,就又不想敲键盘了。

就这样想敲点字,本来挺简单的一件事情,做着做着却开始怀疑这么做的意义,从而进入一种纠结的状态。为了破除这种状态,在没有好的技术可分享,有见地的文章可写的情况下,我也只能在一些不怎么高明的技术分享或者无病呻吟的文章中上下求索咯。坚持一周几篇的频率,期待着哪一天能够写出一些质量稍微好的技术分享或者文章。

MVP初识

发表于 2016-01-08   |   分类于 Android

MVP已经学习两天,依然不知道如何下手去整一个MVP的Android APP,但是其思想是值得记住的。在后面写代码的时候时刻记住就好,就像脑子中时刻想这命名的重要性以及不要复制自己的原则,在写代码时会刻意的去取个自己容易理解的名字,抑或是看到两段差不多的代码,就想着把公共的部分提炼出来。代码最好也未必就变得特别容易阅读,至少自己在一两个月过后还是能够比较快一点的明白自己在表达是什么,不过也有无法想起的时候。

所以我记住MVP的一些基本原则,后面写代码时多想想,刻意训练下,代码应该会更容易懂点。现在说说自己对MVP学习这件事情之后的一些理解。

学习的是MVP,但思想并不是局限于MVP,他和其他的模式如MVC、MVVM之类的目的其实是一样的。都是要使得代码更加简洁优雅。无论是大家对哪种模式的反对与赞同,明白目的一样之后,就没必要为到底选哪一种模式而苦恼,甚至可以在同一个项目中使用多个模式。

那MVP,MVC或者MVVM主要思想是什么呢,主要体现在一下几点,由于参考的文章是英文,也不知道怎么翻译才足够准确,就原文复制下来。

  • Independent of Frameworks.

  • Testable.

  • Independent of UI.

  • Independent of Database.

  • Independent of any external agency.

MVP图解

具体的请参考这篇博文.

如图说明一样,各个模块彼此独立,而且里面的圈一定不要依赖外面的圈,只能外面的圈依赖里面的圈。现在还是不能很好的理解,得动手试试并多想想场景才能够很好的理解。总之,写代码的时候多想想用什么方式使得代码更简洁就好。

我对加班的一些想法与态度

发表于 2016-01-07   |   分类于 杂谈
写在“加班”前的话

近来要为自己的APP添加功能或者修改Bug的时候,常常觉得自己的项目不够简洁。各个类与方法非常混乱,而且Activity是个God Class,让人感觉代码不够简洁不够优雅。今天看到MVP架构,从头到尾理解,但是并没有理解透彻,准备写完简单Demo来实践该架构,再来说明一下自己的理解。

回归正题

这几年工作过的项目,往往在项目前期或者上线的时候有过大幅度加班。而项目趋于稳定或者没什么项目可做的时候,就没有加过班。下面的话全是自己的经历与理解,并没有大量的数据进行验证。如有问题,也仅是自己的个人观点,欢迎讨论。

在加班的时间里大概有两种情况。

一种是对于一门技术的不了解,工作的时候总有许多内容需要一边学习一边实验的,导致需要一些额外的时间才能够完成工作。这个在我看来是正常的,往往这个时候也没觉得自己是在加班。也就是说专注解决问题的时候,没有意识到这是属于额外的工作,反而在解决完问题的时候,有一定的成就感。

另外一种情况是项目工期特别紧,需要加班加点的完成工作。到最后也许依然不能够完成工作,或者勉强完成工作,只是工作质量就有待考察。对于这种加班我觉得是低效的,如果最后发现项目没有签合同时,就感觉之前努力没有什么意思(不过当时那种充实的感觉还是不错的)。

现在不说没有签合同的项目,就单纯的说说项目工期紧张,然后需要天天加班的事情为什么是低效的。因为在我印象中,那种高频的加班(印象中一个月就休息一天),确实每天都在很长时间的工作,只是我不确定一天是否真的有工作十几个小时。我不知道其他人在这种情况下是如何工作的,但我知道我自己并没有一天长时间的工作,总会有开小差的时候,浏览下网页,看一下微博,或者是和朋友聊聊天,然后回归工作。后来看了些书或者一些牛人高效工作的方法,发现我这种开小差的方式明显是影响工作效率的。

以现在的视角来看,工作每天确保高效的工作几个小时可能胜于十几个小时。不仅工作能够完成,还有更多时间去做自己的事情,如读书、锻炼或者学习。而这些事情,在某个层面又会帮助我们提高工作效率。我想我们不应该一门意思的敲代码,偶尔的看看天,是能够帮助我们提高效率的,即使你没有工作那么长时间。

理想状态下,在工期明显有问题的时候,我觉得不应该鼓励大家天天加班,而是应该引导提高工作效率。毕竟加班也只是为了解决效率问题。而解决效率问题方法应该不只一种,还有其他方式,我认为最有效的方式是提高整个团队的编程能力,这个需要团队抽出点时间进行培训,使得项目组的新成员也能够写出漂亮的代码。还有一种就是引导成员自己去学习,而不是一味的写代码。最后,项目如果依然无法限期完成,我觉得需要调整计划,不能一直执行一个不可完成的计划,这个真的会打击整个团队的气势与激情的(关于这个,我也有点想法,可以参考这个这个网址)。

做个总结:

对于加班我的看法是不能够为了加班而加班的,如果这样加班,加班就失去了意义。在适当的时候,加班是没有关系的,例如学习新技术的时候,或者产品上线的一段时间等。这些时候的加班才是有效的,有意义的,能够看到其作用的。最后,我想之所以不能够长期加班,是因为会影响整个团队的士气,无法做到高效的工作,就需要一些休息与调整。自然,如果能够让整个团队天天激情高昂的去做事情,加班与不加班的说法也许就不存在。

一个单词拼写错误引发的效率低下

发表于 2016-01-06   |   分类于 Android

今天为公司的Android APP集成友盟的统计功能。于是打开友盟的帮助文档,从头卡开始浏览,发现集成起来比较方便。于是就开始动手实验。没几下,几行代码就搞定集成,剩下的就是测试。

打开APP,简单点击实验,然后查看友盟的统计数据,发现其渠道数据只有unknown。而实际应该是wandoujia,huawei这写应用厂商的。于是check自己写的代码与官方提供文档是不是有什么出路,仔细核对之后并无出路。

这个时候虽然将代码集成,但是并没有想清楚友盟如何做到渠道统计的。又将其流程过滤一遍,发现只可能是在manifest.xml文件中进行配置。又因为此时生成的apk文件是利用gradle的配置生成的多渠道包,基于自己对Gradle并不是很熟悉,而其配置文件是参考Gradle多渠道打包,我就是在想是不是其渠道的名字没有成功获取到(这个推断是正确的,只是没有想到错误方式居然是…)。

于是我开始用apktool对自己的apk进行反编译想看看manifest.xml文件是否OK,结果发现其渠道值并没有问题,就是我自己想生成的。

在这个时候,我才意思到可能是我配置出现问题,于是去官网将其配置的两个参数名复制,然后在Android Studio中的xml文件进行查找,结果发现UMENG_CHANNEL没有找到,我心想不应该的,这个参数怎么也是配置过的,等我找到这行配置时,才发现我的配置是UMENG_CHANNE。一对比就知道结尾忘记拼写L。

再回头看,本来就几行代码能够完成的功能。我硬是将其过程演变成集成代码 -> 反复核对 -> 反编译 -> 核对查找,这么几个过程。而这个过程从头到尾花去我61分钟,如果说开始单词没有拼写错误的情况下,应该是不要10分钟就能够解决的。这不就是赤裸裸的降低开发效率嘛?

最后用今天学到的一句英文来警示自己,以后尽可能尽可能的少犯这种错误!

Why am I always making the same mistake?

Android博客系列计划

发表于 2016-01-05   |   分类于 Android
写在前面的话

当时好不容易决定维护自己的Blog,目的主要是写点技术相关的东西,顺便写点自己平时想的东西。现在反过来,技术文章基本没有一篇,自己瞎想的东西却已经有那么几篇。今天打开markdown准备编辑的时候,又是准备写些非技术相关的东西。猛然意识到这样完全和自己最初的想法有所偏差。原来还想着随便写点什么,尽量养成一下写点东西的习惯,等把Android技术相关的东西整理清除,再开始写。现在看来,如果不把写技术文章作为首要任务,似乎就永远被遗忘在角落里。因为自己发现,在闲暇时间我总想着写点什么话题好,而忘却弄点什么技术点写出来。

我不禁想:开始一件事情的有效方式是起初就执行,尔后再执行与计划进行循环迭代,在迭代过程中完善,在迭代过程中提高效率。

关于技术

现在还是感觉技术博文比较难写,也不清楚要写些什么。不管怎样,大致先确定以下几个方向,然后慢慢想着。

1
2
3
4
5
6
7
8
9
10
11
12
13
1. Android的一些基本理论学习与总结,一些技术细节的原理等。

2. 在开发现在的项目中,遇到的一些问题总结出来,并说明解决方案。

3. 项目中,哪些地方是需要改善的,应该怎么改善。

4. 用到的开源库,说明其使用方法,或者源码分析,从中学到什么东西。

5. 从项目中,提炼一些通用的东西,然后放到github中,说明其使用方式。

6. 对现在已经使用的技术,但是却不是很清晰的东西,尽量弄清楚来。

7. 自己准备开发一个读书记录的个人项目,开发这个项目的点点滴滴也可以记录。

嗯,这么一看要写的东西方向还是挺多,再好好挤一挤,或许能写点东西出来。:)

1234
王巍

王巍

32 日志
9 分类
1 标签
GitHub 微博
© 2019 王巍
由 Hexo 强力驱动
主题 - NexT.Pisces