1. 程式人生 > >Android 解析RecyclerView(1)——帶點選事件監聽的通用Adapter

Android 解析RecyclerView(1)——帶點選事件監聽的通用Adapter

按照最原始的做法,構建一個RecyclerView Adapter需要寫挺多程式碼的,而通過對Java泛型的使用,可以使程式碼量變得只需十幾行即可。此外,由於RecyclerView不像ListView那樣支援直接新增頂部View,也不支援直接新增點選事件監聽,需要開發者自己通過改造RecyclerView或者RecyclerView Adapter來完成需求。
我打算通過寫三篇文章來對設計“帶點選事件監聽的通用Adapter”和“帶頂部View和底部View的RecyclerView”進行介紹。

本文是對設計通用Adapter的介紹

一、ViewHolder

在使用RecyclerView的過程中,需要用到ViewHolder,在當中對控制元件進行初始化並賦予資料
為了避免每次加RecyclerView的子項時都要對View進行查詢,可以使用SparseArray來儲存View,key值是View ID,Value值則是View

    //用來存放View以減少findViewById的次數
    private SparseArray<View> viewSparseArray;

則每次查詢View時,先從快取中查詢,如果快取中存在則直接返回View,否則還是進行findViewById,找到了後再把View存入快取
利用泛型也可以使返回的View自動轉型

  /**
     * 根據 ID 來獲取 View
     *
     * @param viewId viewID
     * @param <T>    泛型
     * @return 將結果強轉為 View 或 View 的子型別
     */
private <T extends View> T getView(int viewId) { // 先從快取中找,找到的話則直接返回 // 如果找不到則findViewById,再把結果存入快取中 View view = viewSparseArray.get(viewId); if (view == null) { view = itemView.findViewById(viewId); viewSparseArray.put(viewId, view); } return
(T) view; }

由於我們使用到的控制元件一般都是TextView和ImageView,所以預設提供的操作View的方法也是針對這兩個控制元件,可以根據實際情況再來增加

 public CommonRecyclerHolder setText(int viewId, CharSequence text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    public CommonRecyclerHolder setImageResource(int viewId, int resourceId) {
        ImageView imageView = getView(viewId);
        imageView.setImageResource(resourceId);
        return this;
    }

    public CommonRecyclerHolder setImageResource(int viewId, Bitmap bitmap) {
        ImageView imageView = getView(viewId);
        imageView.setImageBitmap(bitmap);
        return this;
    }

    public CommonRecyclerHolder setViewVisibility(int viewId, int visibility) {
        getView(viewId).setVisibility(visibility);
        return this;
    }

為了使RecyclerView支援點選事件監聽,可以在ViewHolder的建構函式中對其進行事件監聽設定。首先需要定義一個通用的點選事件監聽介面,支援短按點選和長按點選

    public interface onClickCommonListener {

        void onClickListener(int position);

        void onLongClickListener(int position);

    }

在View的真實點選事件監聽函式中回撥自定義的監聽介面

private onClickCommonListener clickCommonListener;

 public CommonRecyclerHolder(View itemView) {
        super(itemView);
        viewSparseArray = new SparseArray<>();
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
    }

    public void setClickCommonListener(onClickCommonListener clickCommonListener) {
        this.clickCommonListener = clickCommonListener;
    }

    @Override
    public void onClick(View view) {
        if (clickCommonListener != null) {
            clickCommonListener.onClickListener(getAdapterPosition());
        }
    }

    @Override
    public boolean onLongClick(View view) {
        if (clickCommonListener != null) {
            clickCommonListener.onLongClickListener(getAdapterPosition());
        }
        return true;
    }

總的程式碼如下所示:

/**
 * 通用ViewHolder
 * Created by ZY on 2017/6/3.
 */
public class CommonRecyclerHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {

    public interface onClickCommonListener {

        void onClickListener(int position);

        void onLongClickListener(int position);

    }

    private onClickCommonListener clickCommonListener;

    //用來存放View以減少findViewById的次數
    private SparseArray<View> viewSparseArray;

    public CommonRecyclerHolder(View itemView) {
        super(itemView);
        viewSparseArray = new SparseArray<>();
        itemView.setOnClickListener(this);
        itemView.setOnLongClickListener(this);
    }

    public void setClickCommonListener(onClickCommonListener clickCommonListener) {
        this.clickCommonListener = clickCommonListener;
    }

    @Override
    public void onClick(View view) {
        if (clickCommonListener != null) {
            clickCommonListener.onClickListener(getAdapterPosition());
        }
    }

    @Override
    public boolean onLongClick(View view) {
        if (clickCommonListener != null) {
            clickCommonListener.onLongClickListener(getAdapterPosition());
        }
        return true;
    }

    /**
     * 根據 ID 來獲取 View
     *
     * @param viewId viewID
     * @param <T>    泛型
     * @return 將結果強轉為 View 或 View 的子型別
     */
    private  <T extends View> T getView(int viewId) {
        // 先從快取中找,找到的話則直接返回
        // 如果找不到則findViewById,再把結果存入快取中
        View view = viewSparseArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            viewSparseArray.put(viewId, view);
        }
        return (T) view;
    }

    public CommonRecyclerHolder setText(int viewId, CharSequence text) {
        TextView tv = getView(viewId);
        tv.setText(text);
        return this;
    }

    public CommonRecyclerHolder setImageResource(int viewId, int resourceId) {
        ImageView imageView = getView(viewId);
        imageView.setImageResource(resourceId);
        return this;
    }

    public CommonRecyclerHolder setImageResource(int viewId, Bitmap bitmap) {
        ImageView imageView = getView(viewId);
        imageView.setImageBitmap(bitmap);
        return this;
    }

    public CommonRecyclerHolder setViewVisibility(int viewId, int visibility) {
        getView(viewId).setVisibility(visibility);
        return this;
    }

}

二、RecyclerView Adapter

接下來需要是來改造 RecyclerView Adapter了

在有些時候,有讓RecyclerView的子項呈現不同的佈局的需求,這就需要我們在以下方法中使不同子項返回不同的viewType值了

  public int getItemViewType(int position)

然後,根據不同子項的viewType在以下方法中載入不同的佈局檔案

  public CommonRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType)

為了使我們自定義的RecyclerView Adapter支援多佈局,需要使用到一個介面來返回不同的佈局檔案

    //多佈局支援
    public interface MultiTypeSupport<T> {

        int getLayoutId(T item, int position);

    }

使用泛型來對應不同情況下需要RecyclerView展示的資料集合

    private List<T> dataList;

則 RecyclerView Adapter幾個需要重寫的方法可以如下定義

@Override
    public int getItemViewType(int position) {
        if (multiTypeSupport != null) {
            return multiTypeSupport.getLayoutId(dataList.get(position), position);
        }
        return super.getItemViewType(position);
    }

    @Override
    public CommonRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (multiTypeSupport != null) {
            layoutId = viewType;
        }
        View view = layoutInflater.inflate(layoutId, parent, false);
        return new CommonRecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(CommonRecyclerHolder holder, int position) {
        bindData(holder, dataList.get(position));
        holder.setClickCommonListener(clickCommonListener);
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

宣告一個抽象方法,使子類根據實際情況來進行資料繫結

  protected abstract void bindData(CommonRecyclerHolder holder, T data);

為了對應多種情況,比如有時候需要使用到多個佈局檔案,有時候又需要設定點選事件監聽,所以可以宣告多個建構函式來對應所有的情況

 /**
     * 私有建構函式
     *
     * @param context  上下文
     * @param dataList 資料集合
     */
    private CommonRecyclerAdapter(Context context, List<T> dataList) {
        this.layoutInflater = LayoutInflater.from(context);
        this.dataList = dataList;
    }

    /**
     * 適用於:列表所有的子項都使用相同的佈局檔案,且不需要監聽點選事件
     *
     * @param context  上下文
     * @param dataList 資料集合
     * @param layoutId 佈局檔案ID
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, int layoutId) {
        this(context, dataList);
        this.layoutId = layoutId;
    }

    /**
     * 適用於:列表的子項使用不同的佈局檔案,且不需要監聽點選事件
     *
     * @param context          上下文
     * @param dataList         資料集合
     * @param multiTypeSupport 支援多個佈局檔案
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, MultiTypeSupport<T> multiTypeSupport) {
        this(context, dataList);
        this.multiTypeSupport = multiTypeSupport;
    }

    /**
     * 適用於:列表所有的子項都使用相同的佈局檔案,且需要監聽點選事件
     *
     * @param context             上下文
     * @param dataList            資料集合
     * @param layoutId            佈局檔案ID
     * @param clickCommonListener 點選事件監聽
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, int layoutId,
                                    CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        this(context, dataList, layoutId);
        this.clickCommonListener = clickCommonListener;
    }

    /**
     * 適用於:列表的子項使用不同的佈局檔案,且需要監聽點選事件
     *
     * @param context             上下文
     * @param dataList            資料集合
     * @param multiTypeSupport    支援多個佈局檔案
     * @param clickCommonListener 點選事件監聽
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, MultiTypeSupport<T> multiTypeSupport,
                                    CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        this(context, dataList, multiTypeSupport);
        this.clickCommonListener = clickCommonListener;
    }

總的程式碼如下所示:

/**
 * 通用RecyclerView Adapter
 * Created by ZY on 2017/6/3.
 */
public abstract class CommonRecyclerAdapter<T> extends RecyclerView.Adapter<CommonRecyclerHolder> {

    //多佈局支援
    public interface MultiTypeSupport<T> {

        int getLayoutId(T item, int position);

    }

    private MultiTypeSupport<T> multiTypeSupport;

    private LayoutInflater layoutInflater;

    private List<T> dataList;

    private int layoutId;

    private CommonRecyclerHolder.onClickCommonListener clickCommonListener;

    /**
     * 私有建構函式
     *
     * @param context  上下文
     * @param dataList 資料集合
     */
    private CommonRecyclerAdapter(Context context, List<T> dataList) {
        this.layoutInflater = LayoutInflater.from(context);
        this.dataList = dataList;
    }

    /**
     * 適用於:列表所有的子項都使用相同的佈局檔案,且不需要監聽點選事件
     *
     * @param context  上下文
     * @param dataList 資料集合
     * @param layoutId 佈局檔案ID
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, int layoutId) {
        this(context, dataList);
        this.layoutId = layoutId;
    }

    /**
     * 適用於:列表的子項使用不同的佈局檔案,且不需要監聽點選事件
     *
     * @param context          上下文
     * @param dataList         資料集合
     * @param multiTypeSupport 支援多個佈局檔案
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, MultiTypeSupport<T> multiTypeSupport) {
        this(context, dataList);
        this.multiTypeSupport = multiTypeSupport;
    }

    /**
     * 適用於:列表所有的子項都使用相同的佈局檔案,且需要監聽點選事件
     *
     * @param context             上下文
     * @param dataList            資料集合
     * @param layoutId            佈局檔案ID
     * @param clickCommonListener 點選事件監聽
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, int layoutId,
                                    CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        this(context, dataList, layoutId);
        this.clickCommonListener = clickCommonListener;
    }

    /**
     * 適用於:列表的子項使用不同的佈局檔案,且需要監聽點選事件
     *
     * @param context             上下文
     * @param dataList            資料集合
     * @param multiTypeSupport    支援多個佈局檔案
     * @param clickCommonListener 點選事件監聽
     */
    protected CommonRecyclerAdapter(Context context, List<T> dataList, MultiTypeSupport<T> multiTypeSupport,
                                    CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        this(context, dataList, multiTypeSupport);
        this.clickCommonListener = clickCommonListener;
    }

    @Override
    public int getItemViewType(int position) {
        if (multiTypeSupport != null) {
            return multiTypeSupport.getLayoutId(dataList.get(position), position);
        }
        return super.getItemViewType(position);
    }

    @Override
    public CommonRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (multiTypeSupport != null) {
            layoutId = viewType;
        }
        View view = layoutInflater.inflate(layoutId, parent, false);
        return new CommonRecyclerHolder(view);
    }

    @Override
    public void onBindViewHolder(CommonRecyclerHolder holder, int position) {
        bindData(holder, dataList.get(position));
        holder.setClickCommonListener(clickCommonListener);
    }

    @Override
    public int getItemCount() {
        return dataList.size();
    }

    protected abstract void bindData(CommonRecyclerHolder holder, T data);

}

三、實際使用

首先定義一個Java Bean,方便進行資料傳遞

/**
 * Created by ZY on 2017/6/3.
 */
public class Data {

    private int imageResource;

    private String hintText;

    public Data(int imageResource, String hintText) {
        this.imageResource = imageResource;
        this.hintText = hintText;
    }

    public int getImageResource() {
        return imageResource;
    }

    public String getHintText() {
        return hintText;
    }

}

然後定義一個 item1.xml 和 item2.xml 佈局檔案,來作為RecyclerView的子項要顯示的佈局檔案

item1.xml 的佈局程式碼如下所示, item2.xml 只是更改了背景顏色而已,就不貼出來了

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/iv_head"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_margin="5dp"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:id="@+id/tv_hintText"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textSize="17sp" />

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#abc" />

</LinearLayout>

現在我們定義Adapter子類需要寫的程式碼量就很少了,根據實際情況宣告需要的建構函式即可,不需要每個都寫出來

/**
 * Created by ZY on 2017/6/3.
 */
public class MyCommonRecyclerAdapter extends CommonRecyclerAdapter<Data> {

    public MyCommonRecyclerAdapter(Context context, List<Data> dataList, int layoutId) {
        super(context, dataList, layoutId);
    }

    public MyCommonRecyclerAdapter(Context context, List<Data> dataList, MultiTypeSupport<Data> multiTypeSupport) {
        super(context, dataList, multiTypeSupport);
    }

    public MyCommonRecyclerAdapter(Context context, List<Data> dataList, int layoutId, CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        super(context, dataList, layoutId, clickCommonListener);
    }

    public MyCommonRecyclerAdapter(Context context, List<Data> dataList, MultiTypeSupport<Data> multiTypeSupport, CommonRecyclerHolder.onClickCommonListener clickCommonListener) {
        super(context, dataList, multiTypeSupport, clickCommonListener);
    }

    @Override
    protected void bindData(CommonRecyclerHolder holder, Data data) {
        holder.setImageResource(R.id.iv_head, data.getImageResource())
                .setText(R.id.tv_hintText, data.getHintText());
    }

}

然後,在Activity中宣告使用

Activity的佈局檔案如下所示,兩個按鈕分別用來增添和刪除資料

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.czy.demo.MainActivity">

    <Button
        android:id="@+id/btn_addData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="增添資料" />

    <Button
        android:id="@+id/btn_deleteData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/btn_addData"
        android:text="刪除資料" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_singleDataList"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/btn_deleteData" />

</RelativeLayout>

Activity的所有程式碼如下所示:

public class SingleLayoutActivity extends AppCompatActivity implements CommonRecyclerHolder.onClickCommonListener, View.OnClickListener {

    private List<Data> dataList;

    private MyCommonRecyclerAdapter myCommonRecyclerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_single_layout);
        dataList = new ArrayList<>();
        initData();
        RecyclerView rv_singleDataList = (RecyclerView) findViewById(R.id.rv_singleDataList);
        rv_singleDataList.setLayoutManager(new LinearLayoutManager(this));
        myCommonRecyclerAdapter = new MyCommonRecyclerAdapter(this, dataList, R.layout.item, this);
        rv_singleDataList.setAdapter(myCommonRecyclerAdapter);
        findViewById(R.id.btn_addData).setOnClickListener(this);
        findViewById(R.id.btn_deleteData).setOnClickListener(this);
    }

    private void initData() {
        for (int i = 0; i < 50; i++) {
            Data data = new Data(R.mipmap.ic_launcher_round, "Hi:" + i);
            dataList.add(data);
        }
    }

    @Override
    public void onClickListener(int position) {
        Toast.makeText(this, "點選:" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLongClickListener(int position) {
        Toast.makeText(this, "長按:" + position, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_addData:
                Data data = new Data(R.mipmap.ic_launcher, "Hi");
                dataList.add(data);
                myCommonRecyclerAdapter.notifyDataSetChanged();
                break;
            case R.id.btn_deleteData:
                if (dataList.size() > 0) {
                    dataList.remove(0);
                }
                myCommonRecyclerAdapter.notifyDataSetChanged();
                break;
        }
    }
}

執行效果如下所示:

這裡寫圖片描述

在上面RecyclerView使用的是相同的佈局檔案,可以在宣告myCommonRecyclerAdapter變數時使用另一個建構函式即可支援顯示多佈局

        MyCommonRecyclerAdapter myCommonRecyclerAdapter = new MyCommonRecyclerAdapter(this, dataList, new CommonRecyclerAdapter.MultiTypeSupport<Data>() {
            @Override
            public int getLayoutId(Data item, int position) {
                if (position % 2 == 0) {
                    return R.layout.item;
                }
                return R.layout.item2;
            }
        }, this);

執行效果如下所示:
這裡寫圖片描述

相關推薦

Android 解析RecyclerView1——事件通用Adapter

按照最原始的做法,構建一個RecyclerView Adapter需要寫挺多程式碼的,而通過對Java泛型的使用,可以使程式碼量變得只需十幾行即可。此外,由於RecyclerView不像ListView那樣支援直接新增頂部View,也不支援直接新增點選事件監

示例1按鍵和文本框

基於 所有 click button absolute str over bool stat 參考教程: 3.1.1 基於監聽的事件處理機制 http://www.runoob.com/w3cnote/android-tutorial-listen-event-han

主角人物移動-滑鼠事件與通過射線獲取座標

Ray playerRay;//射線 RaycastHit playerHit;//射線碰撞資訊 Vector3 targetPos;//定義滑鼠點選位置 int mapTargetMask;//定義碰撞層級引數void Start () { //獲取地圖層級

PyQt5筆記02 -- 按鈕事件

本節主要介紹在一個PyQt窗體內新增一個按鈕,滑鼠停留在按鈕上會出現提示,並在點選按鈕時響應一個事件 import sys from PyQt5.QtWidgets import QApplicati

通過事件 setOnClickListener 徹底理解回撥-Android

前言 老司機們對於回撥肯定熟悉得不能再熟悉了,但是新司機可能還是一臉懵逼的,我比較笨,當年懵逼了好久,看夏安明的這一篇部落格地址,雖然下邊的留言都是,寫得好!懂了懂了!但是我當時看了三遍還是不懂好嗎 - -,現在我站在我的角度,用我理解的方式給大家講解回撥,我這麼笨都理解了,聰明的新司機們肯定也

WebView使用詳解——WebViewClient與常用事件

前言:生活的艱難,更會激發對夢想的渴望,但艱難的生活卻往往會成為夢想的絆腳石上篇給大家簡單講了Webview中Native程式碼與JS相互呼叫的方法,這篇我們再講講有關各種攔截與處理的東東。一、WebViewClient1、概述前面我們雖然實現了互動,但可能我們會有一個很簡單

給recyclerAdapter打造通用事件設定BaseRecyclerAdapter

public abstract class BaseRecyclerAdapter<VH extends BaseRecyclerViewHolder> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {

如何對vue中的元件進行事件

<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-default/index.css"> </head> <body> <div id="

百度地圖API 修改起點和終點樣式並刪除事件

準備把開發過程中遇到的一些小問題總結一下,大家如果遇到相同問題,也可以拿來參考。 進入百度地圖   http://developer.baidu.com/map/jsdemo.htm#i5_2 中,如下: 修改程式碼 var driving = new BMap.Driv

一個不錯的HTML5 Canvas多層事件例項

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style

NGUI butten 事件

1.直接監聽 用的少 void OnClick() { Debug.Log("Button is Click!!!"); } 2.新增事件監聽指令碼UIEventTriggert Component—>NGUI —>interactiont—>

Android學習記錄1Android中XML檔案的序列化生成與解析

xml檔案是非常常用的,在android中json和xml是非常常用的兩種封裝資料的形式,從伺服器中獲取資料也經常是這兩種形式的,所以學會生成和解析xml和json是非常有用的,json相對來說是比較簡單的,咱不做介紹了,這裡給大家講一下xml的序列化生成和解析。不廢話了,

android 換膚1——外掛式無縫換膚解析鴻洋大神的換膚流程

對於app換膚,這是一個常見而又常用的功能。雖然我做的專案中還沒涉及到換膚,但是還是想研究下。 於是,下載了鴻洋大神的換膚demo來研究。 先看效果圖:(尊重鴻洋大神的程式碼,效果圖上原創) 鴻洋大神的換膚有兩種: 這兩種我都分析過。各有各的

Android listview子控制元件的的事件

1.先看圖,是否是你想要的   2.佈局檔案<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" androi

藍鯨DevOps深度解析系列1:藍盾平臺總覽

關注嘉為科技,獲取運維新知 2018年10月,嘉為科技與騰訊雲、藍鯨智雲攜手,在北京、上海、廣州、深圳舉辦 “研運一體,資料驅動,讓運維走向運營”為主題的分享會,來自金融、電力、能源、製造等行業的數百家企業到場參加。 在這個分享會上,除了下一代的研發運營體系、基於藍鯨平臺實現企業IT自

解讀Android之Service1基礎知識

本文翻譯自Android官方文件 一個Service是一個長期可以在後臺執行(當然不需要提供UI)的應用元件。其它元件可以啟動service,即使切換到另一個應用,該service仍然可以在後臺執行。另外,其它元件可以繫結一個service進行互動,甚至可以進行程序間通訊(interproces

DSL 系列1 - 擴充套件的論述與實現

前言 DSL 全稱為 domain-specific language(領域特定語言),本系列應當會很長,其中包含些許不成熟的想法,歡迎私信指正。 1. DSL 簡述 我理解的 DSL 的主要職能是對領域的描述,他存在於領域服務之上,如下圖所示: 其實,我們也可以認為 DomainService

10.1java原始碼解析-Integer 1

1類的宣告 public final class Integer extends Number implements Comparable<Integer> 繼承 Number 實現 Comparable<Integer> 可以比較大小

QMUI Android的學習——1引入庫配置主題,並實現沉浸式狀態列效果

最近進行安卓方面的學習,其中用到了騰訊開源的Android UI框架——QMUI Android,這是一個封裝完善的Android UI元件庫,可以給專案的開發提高了很高的工作效率,但是官方的API文件並不是很詳細,所以需要花費時間通過對官方給出的QMUIDEMO進行學習。 這是官方網站:htt

寫給Android App開發人員看的Android底層知識1

這個系列的文章一共8篇,我醞釀了很多年,參考了很多資源,查看了很多原始碼,直到今天把它寫出來,也是戰戰兢兢,生怕什麼地方寫錯了,貽笑大方 (一)引言 早在我還是Android菜鳥的時候,有很多技術我都不太明白,也都找不到答案,比如apk是怎麼安裝的,比如資源是怎