概述:这两天写项目,要求把所有的出表操作换成图。使用HighChart框架可以方便的做出来。但是做的过程当中遇到很多问题,简单记录一下,留着日后看看,可以感慨一下~~

highchart

Highchart真的是一个很棒的框架!

先不说它的扩展性,就是光看它提供的那些图表类型就觉得好厉害的样子。

  • 曲线图
  • 区域图
  • 3D图
  • 柱状图
  • 饼图
  • 散列图
  • 混合图

项目中为了达到复用的目的,写了一个通用的出图模板,以应对每个模块的数据的变化。需要动态的为图标添加数据:

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
var options = {
chart : {
renderTo : 'MonthlyIAE',
type : 'line',
},
title :
legend: { },
xAxis : {
categories : defaultCategories,//x轴数据集
labels: {
rotation: -45 //x轴标签旋转45度
}
},
yAxis : {//y轴
},
},
legend: { //图例
enabled: true
},
credits : { //highchart的版权声明
enabled: false
},
plotOptions : {
series : {
stacking : 'normal'
}
},
scrollbar: { //滚动条
enabled: true
},
series : [ { //线条
name : '',
data : []
} ]
};

动态操作上面对象中的数据

1
2
3
options.xAxis.categories = timeline;//设置X轴-
options.yAxis.title.text= '单位(' + division + ')';//Y轴
options.title.text = title;//TITLE

动态添加线条和数据

1
2
3
4
for(var i = 0; i <newKeylist.length;i++){
options.series[i].name = newKeylist[i];
options.series[i].data = dataArr[i];
}

删除多余图例

1
2
3
4
5
6
7
8

var chart=new Highcharts.Chart(options);
for(var i=0; i < 10;i++){
if(chart.series.length > newKeylist.length){
var j=chart.series.length;
chart.series[j-1].remove();
}
}

动态操作真的很方便,增加了程序的扩展性,让用户很方便的实现需求。

PhotoNoter是一款Material Design风格的开源照片笔记。(MVP+Dagger2+RxJava+Dex分包异步加载),分析MVP模式的项目有点吃力。

一,对启动界面的分析学习。

Jump2xxx方法的回调感觉很好下次可以学习使用

http://7xqumq.com1.z0.glb.clouddn.com/duwei_photonoter.png

一、概述:

Android中太多的东西和Handler-Looper有关了(HandlerThread,IntentService),要想了解他们必须把Handler基础掌握,之前对Handler了解了不知道多少遍,今天终于看了一下源码。还好Handler,Looper,MessageQueue都没有很深的继承结构,代码量也不多,所以看起来比较轻松好理解。

二、从基本的使用开始说起:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Handler mHandler = new Handler(){
@Override
public void handlerMessage(){
//
}
};


new Thread(new Runnable(){
public void run(){
mHandler.sendEmptyMessage(xxx);
}

}).start();

1、首先new一个Handler调用构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}

mLooper = Looper.myLooper();//mLooper对象的初始化
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;//mQueue对象的初始化
mCallback = callback;
mAsynchronous = async;
}

1.1在代码中我们看到初始化了mLooper变量和mQueue变量:

Looper.myLooper()是这样的:

1
2
3
4
5
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}

从装有Looper对象的ThreadLocal中取出一个Looper返回。那么取出来的是哪一个Looper那?我们看一下ThreadLocal的get()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();//看这里
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}

return (T) values.getAfterMiss(this);
}

我们可以确定取出的是当前线程的Looper.

1
mQueue = mLooper.mQueue;

通过上面这句我们知道MessageQueue是在Looper中的。

1
2
3
4
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}

在Looper的私有构造函数中初始化了一个MessageQueue对象。

Looper不断循环MessageQueue中的Message:

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
36
37
38
39
40
41
42
43
44
45
46
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;

// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();

for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}

// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}

msg.target.dispatchMessage(msg);//看这里

if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}

// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}

msg.recycleUnchecked();
}
}

msg.target返回一个Handler对象。调用Handler的dispatchMessage()方法:

1
2
3
4
5
6
7
8
9
10
11
12
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//看这里
}
}

在dispatchMessage方法中又回调了handleMessage(msg)方法


结论:

  • 主线程默认有自己的Looper
  • Looper在不断死循环MessageQueue
  • 死循环中msg.target.dispatchMessage(msg);通过Message将消息扔给Handler
  • 回调Handler的handleMessage方法完成处理

一、系统服务概览

JAVA服务

名称 简介
EntropyService 提供伪随机数
PowerManagerService 电源管理服务
ActivityManagerService 管理Activity
TelephonyRegistry 电话注册、管理服务模块,可以获取电话的链接状态、信号强度等等
PackageManagerService 程序包管理服务,包括对软件包的解包,验证,安装以及升级等
AccountManagerService
ContentService 跨进程数据交换
BatteryService 电池管理服务,监控电池充电及状态的服务,当状态改变时,会广播Intent
HardwareService
SensorService
WindowManagerService Framework最核心的服务之一,负责窗口管理
AlarmManagerService 定时器管理服务,提供定时提醒服务
BluetoothService 蓝牙服务
StatusBarService
ClipboardService 系统剪切板服务
InputMethodManagerService 输入法管理服务
NetStatService 网络状态服务
ConnectivityService 网络连接管理服务
AccessibilityManagerService 主要是一些View获得点击、焦点、文字改变等事件的分发管理
NotificationManagerService 通知栏管理服务,Android中的通知栏和状态栏在一起,只是界面上前者在左边,后者在右边
MountService 挂载服务,可通过该服务调用Linux层面的mount程序,主要负责监听并广播device的mount/unmount/bad removal等等事件。
DeviceStorageMonitorService 磁盘空间状态检测服务
LocationManagerService 地理位置服务
SearchManagerService
CheckinService
WallpaperManagerService
AudioService 音频管理服务
HeadsetObserver 耳机插拔事件的监控小循环
DockObserver 如果系统有个座子,当手机装上或拔出这个座子的话,就得靠他来管理了
BackupManagerService 备份服务
AppWidgetService 桌面小控件
StatusBarPolicy 管理哪个图标该在status bar上显示的策略

获取相关服务:getSystemService(String name)

名称 返回对象 说明
WINDOW_SERVICE WindowManager 管理打开的窗口程序
LAYOUT_INFLATER_SERVICE LayoutInflater 取得xml里定义的view
ACTIVITY_SERVICE ActivityManager 管理应用程序的系统状态
POWER_SERVICE PowerManger 电源的服务
ALARM_SERVICE AlarmManager 闹钟的服务
NOTIFICATION_SERVICE NotificationManager 状态栏的服务
KEYGUARD_SERVICE KeyguardManager 键盘锁的服务
LOCATION_SERVICE LocationManager 位置的服务,如GPS
SEARCH_SERVICE SearchManager 搜索的服务
VIBRATOR_SERVICE Vibrator 手机震动的服务
CONNECTIVITY_SERVICE Connectivity 网络连接的服务
WIFI_SERVICE WifiManager Wi-Fi服务
TELEPHONY_SERVICE TeleponyManager 电话服务