Retrofit2使用和解析(一)

Retrofitsquare公司开源的一个网络访问框架。它将网络请求全部封装起来了,相比较Volley来说更加简单,而且访问接口API更加符合Restful设计。当然Volley也不错哈。Retrofit的代码维护者包括大名鼎鼎的JakeWharton JakeWharton。

Volley解析

Volley是Gooogle I/O 2013发布的一个处理和缓存网络请求的库,能使网络通信更快,更简单,更健壮。Volley名称的由来: a burst or emission of many things or a large amount at once。

2013年volley就有了,分析Volley的文章网上也是一堆一堆的,不过Volley的设计还是值得研究的。

Android屏幕适配总结

直接去参考这3个网站,别的直接去Android官网去看吧~
凯子哥总结的Android屏幕适配全攻略(最权威的官方适配指导)

Android 屏幕适配
适配不同的屏幕

总结下:

mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。
那么如何区分呢?Google官方指定按照下列标准进行区分:
名称 像素密度范围 dip
mdpi 120dpi~160dpi 1.0基准
hdpi 160dpi~240dpi 1.5
xhdpi 240dpi~320dpi 2.0
xxhdpi 320dpi~480dpi 3.0
xxxhdpi 480dpi~640dpi 4.0

  • 1、可以通过使用不同的layout结合不同的dimens来解决。(但是3.2以下版本不支持sw600dp这种限定符的layout,布局可以使用别名)

res/values-large/layout.xml:

1
2
3
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>

1
2
3
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
  • 2、巧妙使用weight。(View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比。)
  • 3、使用9图(9图可以指定内容padding)
  • 4、使用相对布局,绝对不能使用绝对布局
  • 5、使用鸿洋的方式,找一个基准,比如320px*480px的2dip的设备,那么我们将一个屏幕宽度的总像素数平均分成320份,每一份对应具体的像素就可以了。

Android事件分发和处理机制

直接去参考这个网站
触摸事件的传递机制
郭霖的csdn:Android事件分发机制完全解析,带你从源码的角度彻底理解(上)

一些要点:

1、Touch事件是由硬件捕获到触摸后由系统传递给应用的ViewRoot,再由ViewRoot往下一层一层传递.

2、处理过程都是自上而下的分发,可以看成是由布局的“包含”关系,自顶向下的方式

3、事件存在消耗,事件的处理方法都会返回一个boolean值,如果该值为true,则本次事件下发将会被消费掉,而不会继续往下一层传递.

4、Touch事件从ACTION_DOWN开始,也就是按下的这个action开始算起,到ACTION_UP抬起时结束;但是如果在ACTION_DOWN的时候,没有接受事件,那么后续的其他动作也将不会被接受

5、dispatchTouchEvent方法,是用来分发上层传递过来的事件的,它在View和ViewGroup中都有实现

6、onInterceptTouchEvent方法,是用来拦截事件传递的,它只在ViewGroup中有实现,在View中没有

7、view对象的TouchLitener中的onTouch方法总是会先于view自己的onTouchEvent(event)方法被执行,这是由View中的dispatchEvent方法决定。

8、Activity中的onTouchEvent只会在能响应的所有view都响应完事件,且都没有消费掉事件之后才会被调用。

9、如果一个ViewGroup被点击的地方,有多个子View/ViewGroup可以响应点击事件,那么它们响应的顺序是:后addView进来的子view/ViewGroup先响应事件或者是xml布局文件中后被添加的view先 响应触摸事件

Android获取Menu的绘制位置、状态栏和标题栏的高度

Android获取Menu的绘制位置

  • 第一种方式,使用Compat兼容包,通过setActionView
1
2
3
4
5
6
7
public boolean onCreateOptionsMenu(final Menu menu) {
this.menu = menu;
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
final ImageView iv = new ImageView(this);
iv.setImageResource(R.drawable.home_history_btn_selector);
MenuItemCompat.setActionView(menu.findItem(R.id.action_history), iv);

然后通过getActionView获取到图片,进而获取位置

1
2
3
4
5
6
View view = MenuItemCompat.getActionView(menu.findItem(R.id.action_history));
if(view == null){
return;
}
int location[] = new int[2];
view.getLocationInWindow(location);

但这个方式比较坑的一点是,MenuItemCompat.setActionView后,改MenuItem不能相应点击事件了,只能通过给ImageView设置监听的方式响应事件;而且menu的响应和正常的menu样式不一样,长按效果消失。

  • 第二种方式比较简单,因为menu在Android中最终绘制为View,所以可以通过findViewById的方式获取到对应的View.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {

    View view = findViewById(R.id.action_history);
    if (view != null) {
    int[] location = new int[2];
    view.getLocationInWindow(location);
    Log.d(TAG, "x=" + location[0] + " y=" + location[1]);
    getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }
    });

获取状态栏的高度

1
2
3
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;

获取标题栏的高度

1
2
3
int contentTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();
//statusBarHeight是上面所求的状态栏的高度
int titleBarHeight = contentTop - statusBarHeight; (statusBarHeight见上)

android-async-http解析和使用

loopj/android-async-http github地址
官网

Features

  • Make asynchronous HTTP requests, handle responses in anonymous callbacks
    发送异步http请求,在匿名callback对象中处理response信息;
  • HTTP requests happen outside the UI thread
    http请求发生在UI(主)线程之外的异步线程中;
  • Requests use a threadpool to cap concurrent resource usage
    内部采用线程池来处理并发请求;
  • GET/POST params builder (RequestParams)
    通过RequestParams类构造GET/POST,Builder方式。
  • Multipart file uploads with no additional third party libraries
    内置多部分文件上传,不需要第三方库支持;
  • Tiny size overhead to your application, only 60kb for everything
    和你的app大小相比来说,库的size很小,所有的一切只有90kb;
  • Automatic smart request retries optimized for spotty mobile connections
    在各种各样的移动连接环境中具备自动智能请求重试机制;
  • Automatic gzip response decoding support for super-fast requests
    自动的gzip响应解码
  • Optional built-in response parsing into JSON (JsonHttpResponseHandler)
    内置多种形式的响应解析,有原生的字节流,string,json对象,甚至可以将response写到文件中
  • Optional persistent cookie store, saves cookies into your app’s SharedPreferences
    cookie保存,内部实现用的是Android的SharedPreferences;

Window和WindowManager

bugly也写了一篇更详细的
浅析Android的窗口
windowmanager 使用 demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
WindowManager mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Button mFloatingButton = new Button(this);
mFloatingButton.setText("click me");
WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 0, 0,
PixelFormat.TRANSPARENT);
mLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_SHOW_WHEN_LOCKED;
mLayoutParams.type = LayoutParams.TYPE_SYSTEM_ERROR;
mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
mLayoutParams.x = 100;
mLayoutParams.y = 300;
mWindowManager.addView(mFloatingButton, mLayoutParams);

注意:小米等手机进行了framework的修改,所以不能正常显示悬浮窗,需要自己去设置中心里面设置允许弹窗。

详解LayoutInfalter.inflate

LayoutInflater的2种初始化方式

  • 1、LayoutInflater.from(this)
  • 2、 LayoutInflater LayoutInflater =
    (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    

然而本质上都是一样的。

Fork me on GitHub