A view that makes it easy to debug response data.(一个可以方便调试响应数据的视图。)

Overview

JSONRecyclerView

该控件可以方便调试响应数据,如下图所示:

JSONRecyclerViewDemo.gif

控件的样式参考以下这个网站:

JSON在线解析解析及格式化验证

项目的GitHub:JSONRecyclerView

项目Demo的GitHub:JSONRecyclerViewDemo

概述

控件是以RecyclerView为基础,文本会呈现相应的颜色以反映对应的类型,如果值的类型为JSONObject或者JSONArray,该数据对应的视图可以展开或者收缩,除此之外,文本的大小或者颜色都可以自定义更改。

文本分为以下七种类型

  • 普通文本冒号花括号中括号逗号Object{...}Array[]
  • key类型的文本
  • String类型的文本
  • Number类型的文本
  • Boolean类型的文本
  • url文本
  • null文本

默认文本颜色如下所示:

#333333 #92278f #3ab54a #25aae2 #f98280 #61d2d6 #f1592a ">
<color name="default_text_color">#333333color>
<color name="default_key_color">#92278fcolor>
<color name="default_string_color">#3ab54acolor>
<color name="default_number_color">#25aae2color>
<color name="default_boolean_color">#f98280color>
<color name="default_url_color">#61d2d6color>
<color name="default_null_color">#f1592acolor>

使用方法

使用方法如下所示:

导入到项目

通过以下代码导入到你的项目:

dependencies {
    implementation 'com.github.TanJiaJunBeyond:JSONRecyclerView:1.0.0'
}

添加到视图

然后将JsonRecyclerView添加到xml文件中,代码如下所示:

">
<com.tanjiajun.jsonrecyclerview.view.JSONRecyclerView
    android:id="@+id/rv_json"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

或者通过addView相关的方法添加到视图中,代码如下所示:

val rvJson = JSONRecyclerView(this)
linearLayout.addView(rvJson)

我们可以通过setStyle方法改变样式,代码如下所示:

rvJson.setStyles(textColor = ContextCompat.getColor(this,R.color.black))

绑定数据

通过bindData方法绑定数据,接受JSON字符串JSONObjectJSONArray三种类型的数据。

当我们数据类型是JSON字符串的时候,可以调用以下方法:

// JSONRecyclerView.kt
/**
 * 绑定JSON字符串数据。
 * Bind the json string data.
 *
 * @param jsonString The json string to bind.(要绑定的JSON字符串。)
 */
fun bindData(jsonString: String) =
        adapter.bindData(jsonString)

当我们数据类型是JSONObject的时候,可以调用以下方法:

// JSONRecyclerView.kt
/**
 * 绑定JSONObject数据。
 * Bind the json object data.
 *
 * @param jsonObject The json object to bind.(要绑定的JSONObject。)
*/
fun bindData(jsonObject: JSONObject) =
        adapter.bindData(jsonObject)	

当我们数据类型是JSONArray的时候,可以调用以下方法:

// JSONRecyclerView.kt
/**
 * 绑定JSONArray数据。
 * Bind the json array data.
 *
 * @param jsonArray The json array to bind.(要绑定的JSONArray。)
*/
fun bindData(jsonArray: JSONArray) =
        adapter.bindData(jsonArray)

示例代码

代码如下所示:

package com.tanjiajun.jsonrecyclerviewdemo

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.tanjiajun.jsonrecyclerview.view.JSONRecyclerView

/**
 * Created by TanJiaJun on 6/1/21.
 */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<JSONRecyclerView>(R.id.rv_json).bindData(
            "{\n" +
                    "    \"string\":\"string\",\n" +
                    "    \"number\":100,\n" +
                    "    \"boolean\":true,\n" +
                    "    \"url\":\"https://github.com/TanJiaJunBeyond/JSONRecyclerView\",\n" +
                    "    \"JSONObject\":{\n" +
                    "        \"string\":\"string\",\n" +
                    "        \"number\":100,\n" +
                    "        \"boolean\":true\n" +
                    "    },\n" +
                    "    \"JSONArray\":[\n" +
                    "        {\n" +
                    "            \"string\":\"string\",\n" +
                    "            \"number\":100,\n" +
                    "            \"boolean\":true\n" +
                    "        }\n" +
                    "    ]\n" +
                    "}"
        )
    }

}

核心代码

大部分代码都有中英文对应的注释,可能有些地方翻译地不太好,请各位见谅哈。

上面也提到了,该控件是以RecyclerView为基础,涉及到JsonItemViewJsonViewAdapterJsonRecyclerView三个类。

JSONItemView

该类用于展示每一条数据对应的视图,用到的布局文件item_json_view.xml,它继承LinearLayout,有四个关键的变量,代码如下所示:

// JSONItemView.kt
private lateinit var tvLeft: TextView
private lateinit var ivIcon: ImageView
private lateinit var tvRight: TextView

/**
 * Set the scaled pixel text size.
 * 设置文本大小。
 */
var textSize = DEFAULT_TEXT_SIZE_SP
    set(value) {
        // 范围是[12.0F,30.0F]
        field = when {
            value < 12.0F -> 12.0F
            value > 30.0F -> 30.0F
            else -> value
        }
        // 设置左边文本的文字大小
        tvLeft.textSize = field
        // 设置展示展开和收缩图标的大小
        val size = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            field,
            resources.displayMetrics
        ).toInt()
        ivIcon.layoutParams = (ivIcon.layoutParams as LinearLayout.LayoutParams).apply {
            width = size
            height = size
        }
        // 设置右边文本的文字大小
        tvRight.textSize = field
    }
  • 变量tvLeft左边TextView,用于展示key相关的文本

  • 变量ivIcon中间ImageView,用于展示展开或者收缩的图标

  • 变量tvRight右边TextView,用于展示value相关的文本

  • 变量textSizepublic的变量,可以通过该变量改变文本的大小,要注意的是,单位是sp,无论是赋多大或者多小值,文本的最小值12sp最大值30sp

JSONViewAdapter

该类用于处理不同类型的数据和点击相关的逻辑,它继承RecyclerView.Adapter,主要涉及到如下几个关键的方法:

onBindViewHolder方法

代码如下所示:

// JSONViewAdapter.kt
override fun onBindViewHolder(holder: JSONViewAdapter.JsonItemViewHolder, position: Int) {
    with(holder.jsonItemView) {
        textSize = this@JSONViewAdapter.textSize
        setRightColor(textColor)
        jsonObject?.let { bindJSONObjectData(position, it) }
        jsonArray?.let { bindJSONArrayData(position, it) }
    }
}

作用是将数据绑定到视图,如果数据类型是JSONObject,就调用bindJSONObjectData方法,如果数据类型是JSONArray,就调用bindJSONArrayData方法。

handleValue方法

代码如下所示:

// JSONViewAdapter.kt
/**
 * Handle the styling of the right part of the json item view (i.e., the part that shows the value).
 * 处理JsonItemView右边部分的样式(即展示值的部分)。
 *
 * @param value The value to be displayed in the json item view.(要在JsonItemView展示的value。)
 * @param itemView The json item view to be processed.(要处理的JsonItemView对象。)
 * @param appendComma Whether to append commas.(是否附加逗号。)
 * @param hierarchy The number of view hierarchies.(View的层次结构数量。)
 */
private fun handleValue(
    value: Any?,
    itemView: JSONItemView,
    appendComma: Boolean,
    hierarchy: Int
) {
    itemView.showRight(SpannableStringBuilder().apply {
        when (value) {
            is Number ->
                // 处理值为Number类型的样式
                handleNumberValue(itemView, value)
            is Boolean ->
                // 处理值为Boolean类型的样式
                handleBooleanValue(itemView, value)
            is String ->
                // 处理值为String类型的样式
                handleStringValue(itemView, value)
            is JSONObject ->
                // 处理值为JSONObject类型的样式
                handleJSONObjectValue(itemView, value, appendComma, hierarchy)
            is JSONArray ->
                // 处理值为JSONArray类型的样式
                handleJSONArrayValue(itemView, value, appendComma, hierarchy)
            else ->
                // 处理值为null的样式
                handleNullValue(itemView)
        }
        if (appendComma) append(",")
    })
}

onClick方法

如果数据类型是JSONObject或者JSONArray的话,可以通过点击展开或者收缩视图,代码如下所示:

如果是第一次展开,就调用performFirstExpand方法,否则就调用performClick方法,代码如下所示:

// JSONViewAdapter.kt
override fun onClick(v: View?) {
    // 如果itemView的子View数量是1,就证明这是第一次展开
    (itemView.childCount == 1)
        .yes { performFirstExpand() }
        .otherwise { performClick() }
}

performFirstExpand方法

该方法用于第一次展开JSONObject或者JSONArray对应的itemView,代码如下所示:

// JSONViewAdapter.kt
/**
 * The first time the view corresponding to a JSONObject or JSONArray is expanded.
 * 第一次展开JSONObject或者JSONArray对应的itemView。
 */
private fun performFirstExpand() {
    isExpanded = true
    itemView.showIcon(false)
    itemView.tag = itemView.getRightText()
    itemView.showRight(if (isJsonObject) "{" else "[")

    // 展开该层级以下的视图
    val array: JSONArray? =
        if (isJsonObject) (value as JSONObject).names() else value as JSONArray
    val length = array?.length() ?: 0
    for (i in 0 until length) {
        itemView.addViewNoInvalidate(JSONItemView(itemView.context).apply {
            textSize = this@JSONViewAdapter.textSize
            setRightColor(textColor)
            val childValue = array?.opt(i)
            isJsonObject
                .yes {
                    handleJSONObject(
                        key = childValue as String,
                        value = (value as JSONObject)[childValue],
                        appendComma = i < length - 1,
                        hierarchy = hierarchy
                    )
                }
                .otherwise {
                    handleJSONArray(
                        value = childValue,
                        appendComma = i < length - 1,
                        hierarchy = hierarchy
                    )
                }
        })
    }
    // 展示该层级最后的一个视图
    itemView.addViewNoInvalidate(JSONItemView(itemView.context).apply {
        textSize = this@JSONViewAdapter.textSize
        setRightColor(textColor)
        showRight(
            StringBuilder(getHierarchyStr(hierarchy - 1))
                .append(if (isJsonObject) "}" else "]")
                .append(if (appendComma) "," else "")
        )
    })
    // 重绘itemView
    itemView.requestLayout()
    itemView.invalidate()
}

performClick方法

该方法用于点击后展开或者收缩,代码如下所示:

/**
 * Click to expand or collapse.
 * 点击后展开或者收缩。
 */
private fun performClick() {
    itemView.showIcon(isExpanded)
    val rightText = itemView.getRightText()
    itemView.showRight(itemView.tag as CharSequence)
    itemView.tag = rightText
    for (i in 1 until itemView.childCount) {
        // 如果展开的话,就把子View都设成可见状态,否则就设为隐藏状态
        itemView.getChildAt(i).visibility = if (isExpanded) View.GONE else View.VISIBLE
    }
    isExpanded = !isExpanded
}

如果数据类型是url的话,可以通过点击来打开浏览器查看,代码如下所示:

/**
 * Click to expand or collapse.
 * 点击后展开或者收缩。
 */
private fun performClick() {
    itemView.showIcon(isExpanded)
    val rightText = itemView.getRightText()
    itemView.showRight(itemView.tag as CharSequence)
    itemView.tag = rightText
    for (i in 1 until itemView.childCount) {
        // 如果展开的话,就把子View都设成可见状态,否则就设为隐藏状态
        itemView.getChildAt(i).visibility = if (isExpanded) View.GONE else View.VISIBLE
    }
    isExpanded = !isExpanded
}

判断是否是url类型的正则表达式如下所示,注释已经写得很详细,这里就不再赘述:

private val urlPattern: Pattern = Pattern.compile(
    // 验证是否是http://、https://、ftp://、rtsp://、mms://其中一个
    "((http|https|ftp|rtsp|mms)?://)?" +
            // 判断字符是否为FTP地址(ftp://user:password@)
            // 判断字符是否为0到9、小写字母a到z、_、!、~、*、'、(、)、.、&、=、+、$、%、-其中一个,匹配零次或者一次
            "(([0-9a-z_!~*'().&=+\$%-]+: )?" +
            // 判断字符是否为0到9、小写字母a到z、_、!、~、*、'、(、)、.、&、=、+、$、%、-其中一个,匹配一次或者多次
            "[0-9a-z_!~*'().&=+\$%-]+" +
            // @
            "@)?" +
            // 判断字符是否为IP地址,例子:192.168.255.255
            // 判断字符是否匹配1+[0到9,匹配两次],例如:192
            "((1\\d{2}" +
            // 或者
            "|" +
            // 判断字符是否匹配2+[0到4,匹配一次]+[0到9,匹配一次],例如:225
            "2[0-4]\\d" +
            // 或者
            "|" +
            // 判断字符是否匹配25+[0到5,匹配一次],例如:255
            "25[0-5]" +
            // 或者
            "|" +
            // 判断字符是否匹配[1到9,匹配一次]+[0到9,匹配一次],例如:25
            "[1-9]\\d" +
            // 或者
            "|" +
            // 判断字符是否匹配1到9,匹配一次,例如:5
            "[1-9])" +
            // 判断字符是否匹配\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d),匹配三次
            "(\\.(" +
            // 判断字符是否匹配1+[0到9,匹配两次],例如:192
            "1\\d{2}" +
            // 或者
            "|" +
            // 判断字符是否匹配2+[0到4,匹配一次]+[0到9,匹配一次],例如:225
            "2[0-4]\\d" +
            // 或者
            "|" +
            // 判断字符是否匹配25+[0到5,匹配一次],例如:255
            "25[0-5]" +
            // 或者
            "|" +
            // 判断字符是否匹配[1到9]+[0到9],例如:25
            "[1-9]\\d" +
            // 或者
            "|" +
            // 判断字符是否匹配0到9,匹配一次,例如:5
            "\\d))" +
            // 匹配三次
            "{3}" +
            // 或者
            "|" +
            // 判断字符是否为域名(Domain Name)
            // 三级域名或者以上,判断字符是否为0到9、小写字母a到z、_、!、~、*、'、(、)、-其中一个,匹配零次或者多次,然后加上.,例如:www.
            "([0-9a-z_!~*'()-]+\\.)*" +
            // 二级域名,长度不能超过63个字符,先判断第一个字符是否为0到9、小写字母a到z其中一个,匹配一次,然后判断第二个字符是否为0到9、小写字母a到z、-其中一个,最多匹配61次,这两个字符匹配零次或者一次,最后判断第三个字符是否为0到9、小写字母a到z其中一个,然后加上.
            "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]" +
            // 顶级域名,判断字符是否为小写字母a到z其中一个,匹配最少两次、最多六次,例如:.com、.cn
            "\\.[a-z]{2,6})" +
            // 端口号,判断字符是否匹配:+[0到9,匹配最少一次、最多四次],匹配零次或者一次
            "(:[0-9]{1,4})?" +
            // 判断字符是否为斜杠(/),匹配零次或者一次,如果没有文件名,就不需要斜杠
            "((/?)|" +
            // 判断字符是否为0到9、小写字母a到z、大写字母A到Z、_、!、~、*、'、(、)、.、;、?、:、@、&、=、+、$、,、%、#、-其中一个,匹配一次或者多次
            "(/[0-9a-zA-Z_!~*'(){}.;?:@&=+\$,%#-]+)+" +
            // 判断字符是否为斜杠(/),匹配零次或者一次
            "/?)\$"
)

正则表达式可视化图如下所示:

UrlRegularExpression.png

JSONRecyclerView

该类用于将要处理的数据以列表的方式展示到视图,注释写得比较清楚,这里就不再赘述了,代码如下所示:

// JSONRecyclerView.kt
package com.tanjiajun.widget

import android.content.Context
import android.util.AttributeSet
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tanjiajun.widget.R
import com.tanjiajun.widget.JSONViewAdapter
import com.tanjiajun.widget.DEFAULT_TEXT_SIZE_SP
import org.json.JSONArray
import org.json.JSONObject

/**
 * Created by TanJiaJun on 5/31/21.
 */
class JSONRecyclerView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {

    private val adapter = JSONViewAdapter(context)

    init {
        layoutManager = LinearLayoutManager(context)
        setAdapter(adapter)
    }

    /**
     * 绑定JSON字符串数据。
     * Bind the json string data.
     *
     * @param jsonString The json string to bind.(要绑定的JSON字符串。)
     */
    fun bindData(jsonString: String) =
        adapter.bindData(jsonString)

    /**
     * 绑定JSONObject数据。
     * Bind the json object data.
     *
     * @param jsonObject The json object to bind.(要绑定的JSONObject。)
     */
    fun bindData(jsonObject: JSONObject) =
        adapter.bindData(jsonObject)

    /**
     * 绑定JSONArray数据。
     * Bind the json array data.
     *
     * @param jsonArray The json array to bind.(要绑定的JSONArray。)
     */
    fun bindData(jsonArray: JSONArray) =
        adapter.bindData(jsonArray)

    /**
     * 设置JsonItemView的样式。
     * Set the json item view styles.
     *
     * @param textSize The size of all text.(所有文本的大小。)
     * @param textColor The normal text color.(普通文本的颜色)
     * @param keyColor The color of the text of type key.(key类型文本的颜色。)
     * @param stringColor The color of the text of type String.(字符串类型文本的颜色。)
     * @param numberColor The color of the text of type Number.(Number类型文本的颜色。)
     * @param booleanColor The color of text of type Boolean.(Boolean类型文本的颜色。)
     * @param urlColor The color of url text.(url文本的颜色。)
     * @param nullColor The color of null text.(null文本的颜色。)
     */
    @JvmOverloads
    fun setStyles(
        textSize: Float = DEFAULT_TEXT_SIZE_SP,
        @ColorInt textColor: Int = ContextCompat.getColor(context, R.color.default_text_color),
        @ColorInt keyColor: Int = ContextCompat.getColor(context, R.color.default_key_color),
        @ColorInt stringColor: Int = ContextCompat.getColor(context, R.color.default_string_color),
        @ColorInt numberColor: Int = ContextCompat.getColor(context, R.color.default_number_color),
        @ColorInt booleanColor: Int = ContextCompat.getColor(
            context,
            R.color.default_boolean_color
        ),
        @ColorInt urlColor: Int = ContextCompat.getColor(context, R.color.default_url_color),
        @ColorInt nullColor: Int = ContextCompat.getColor(context, R.color.default_null_color)
    ) {
        with(adapter) {
            this.textSize = when {
                textSize < MIN_TEXT_SIZE -> MIN_TEXT_SIZE
                textSize > MAX_TEXT_SIZE -> MAX_TEXT_SIZE
                else -> textSize
            }
            this.textColor = textColor
            this.keyColor = keyColor
            this.stringColor = stringColor
            this.numberColor = numberColor
            this.booleanColor = booleanColor
            this.urlColor = urlColor
            this.nullColor = nullColor
            // 刷新列表
            notifyDataSetChanged()
        }
    }

    private companion object {
        const val MIN_TEXT_SIZE = 12.0F
        const val MAX_TEXT_SIZE = 24.0F
    }

}

题外话

介绍一个将正则表达式可视化的网站,网址如下:

Regexper

我的GitHub:TanJiaJunBeyond

Android通用框架:Android通用框架

我的掘金:谭嘉俊

我的简书:谭嘉俊

我的CSDN:谭嘉俊

You might also like...
Easy Response Mocking for Retrofit using annotations

Response Mocking for Retrofit using annotations. Assume Provides safe and easy way to mock API responses for retrofit-okhttp3.

Expandable Recyclerview makes it easy to integrate nested recycler view...🔨 📝
Expandable Recyclerview makes it easy to integrate nested recycler view...🔨 📝

SSExpandableRecyclerView Expandable Recyclerview make it easy to integrate nested recyclerview Features Simple and easy to use ( no complex adapter re

Under the Hood is a flexible and powerful Android debug view library. It uses a modular template system that can be easily extended to your needs, although coming with many useful elements built-in.
Under the Hood is a flexible and powerful Android debug view library. It uses a modular template system that can be easily extended to your needs, although coming with many useful elements built-in.

Under the Hood - Android App Debug View Library Under the Hood is a flexible and powerful Android debug view library. It uses a modular template syste

A customizable debug screen to view and edit flags that can be used for development in Jetpack Compose applications
A customizable debug screen to view and edit flags that can be used for development in Jetpack Compose applications

Tweaks A customizable debug screen to view and edit flags that can be used for development in Jetpack Compose applications To include the library add

Tweaks - A customizable debug screen to view and edit flags that can be used for development
Tweaks - A customizable debug screen to view and edit flags that can be used for development

A customizable debug screen to view and edit flags that can be used for developm

An OkHttp interceptor which has pretty logger for request and response. +Mock support
An OkHttp interceptor which has pretty logger for request and response. +Mock support

LoggingInterceptor - Interceptor for OkHttp3 with pretty logger Usage val client = OkHttpClient.Builder() client.addInterceptor(LoggingInterceptor

LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently.

Android network framework: LiteHttp Tags : litehttp2.x-tutorials Website : http://litesuits.com QQgroup : 42960650 , 47357508 Android网络通信为啥子选 lite-htt

Raccoon is a lightweight response mocking framework that can be easily integrated into the Android UI tests.
Raccoon is a lightweight response mocking framework that can be easily integrated into the Android UI tests.

Raccoon Medium Articles Checkout these article to get more insights about this library: How to integrate this in your Android Test Why Raccoon? There

TART: Tracing Action Response Times

Square Tart Tracing Action Response Times! This library is not stable for usage beyond Square, the APIs and internals might change anytime. Tart... ?

A small Android project to practice executing network requests and parsing the network response
A small Android project to practice executing network requests and parsing the network response

InspirationalQuotesExercise A small Android project to practice executing network requests and parsing the network response This app uses the ZenQuote

An auto IBCS API response status checking tool which test tax, address and account module

IB IBCS API Test Tool An auto IBCS API response status checking tool which test tax, address and account module. Getting Started Cd to the cloned dire

A simple covid-19 response application to give users an idea of the severity of their covid-19 status and profer steps to take based on the severity.
A simple covid-19 response application to give users an idea of the severity of their covid-19 status and profer steps to take based on the severity.

COVID-19 Response 🎡 A simple covid-19 response application to give users an idea of the severity of their covid-19 status and profer steps to take ba

Handy library to integrate pagination, which allow no data layout, refresh layout, recycler view in one view and easy way to bind pagination in app.
Handy library to integrate pagination, which allow no data layout, refresh layout, recycler view in one view and easy way to bind pagination in app.

Pagination View Handy library to integrate pagination, which allow no data layout, refresh layout, recycler view in one view and easy way to bind pagi

Repo of the Open Source Android library : RoboSpice. RoboSpice is a modular android library that makes writing asynchronous long running tasks easy. It is specialized in network requests, supports caching and offers REST requests out-of-the box using extension modules. 📱 AppListManager (Android Library) makes managing application and activity lists easy.
📱 AppListManager (Android Library) makes managing application and activity lists easy.

AppListManager (Android Library) AppListManager is easy to use Android library, which minimizes developing time when working on application or activit

This library provides Easy Android ListView Adapters(EasyListAdapter & EasyCursorAdapter) which makes designing Multi-Row-Type ListView very simple & cleaner, It also provides many useful features for ListView.
This library provides Easy Android ListView Adapters(EasyListAdapter & EasyCursorAdapter) which makes designing Multi-Row-Type ListView very simple & cleaner, It also provides many useful features for ListView.

EasyListViewAdapters Whenever you want to display custom items in listview, then only way to achieve this is to implement your own subclass of BaseAda

An Android library that makes developers use SQLite database extremely easy.

LitePal for Android 中文文档 LitePal is an open source Android library that allows developers to use SQLite database extremely easy. You can finish most o

****. Use the native and support library variants instead - https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html. An android library that makes it easy to add custom fonts to edittexts and textviews

Add to your project Add this line to your dependencies in build.gradle compile 'in.workarounds.typography:typography:0.0.8' Using the views There are

Android library which makes it  easy to handle the different obstacles while calling an API (Web Service) in Android App.
Android library which makes it easy to handle the different obstacles while calling an API (Web Service) in Android App.

API Calling Flow API Calling Flow is a Android library which can help you to simplify handling different conditions while calling an API (Web Service)

Owner
TanJiaJun
TanJiaJun
Stetho is a debug bridge for Android applications, enabling the powerful Chrome Developer Tools and much more.

Stetho Stetho is a sophisticated debug bridge for Android applications. When enabled, developers have access to the Chrome Developer Tools feature nat

Facebook 12.6k Jan 7, 2023
Android QA/Debug tools to speed up and streamline the development progress.

Android Dev Tools is a library that contains various QA/Debug tools to speed up and streamline the development progress.

Trendyol Open Source 105 Dec 5, 2022
Easy android exception tracer and handler.

Introduction Lup is a small android library that can help you to tracking bug that causes application stopped working (force close). Whiting this libr

icodeu 4 Sep 29, 2022
Sandwich was invented for constructing the standardized response interface from the network response

?? A lightweight and standardized Android network response interface for handling successful data and error responses.

Jaewoong Eum 973 Jan 5, 2023
🍼Debug Bottle is an Android runtime debug / develop tools written using kotlin language.

???? 中文 / ???? 日本語 / ???? English ?? Debug Bottle An Android debug / develop tools written using Kotlin language. All the features in Debug bottle are

Yuriel Arlencloyn 846 Nov 14, 2022
🍼Debug Bottle is an Android runtime debug / develop tools written using kotlin language.

???? 中文 / ???? 日本語 / ???? English ?? Debug Bottle An Android debug / develop tools written using Kotlin language. All the features in Debug bottle are

Yuriel Arlencloyn 846 Nov 14, 2022
null 2.4k Dec 30, 2022