<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>xiaoming.eth</title>
        <link>https://paragraph.com/@xiaoming</link>
        <description>undefined</description>
        <lastBuildDate>Mon, 06 Jul 2026 15:22:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>xiaoming.eth</title>
            <url>https://storage.googleapis.com/papyrus_images/378a13cb50dcb3b9464501b5ec0f7268913fa960bba4c87ce1638858805cebe4.png</url>
            <link>https://paragraph.com/@xiaoming</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[欧易okx怎么购买BTC？欧易交易所买卖BTC全教程]]></title>
            <link>https://paragraph.com/@xiaoming/okx-btc-btc</link>
            <guid>Vi9YqfIJZqtOgT2b99FP</guid>
            <pubDate>Tue, 24 Dec 2024 07:40:35 GMT</pubDate>
            <description><![CDATA[https://chouyi.army/join/4722426 1️⃣ 打开 App 首页，点击【我要买币】，选择【C2C买币】。2️⃣ 进入【C2C交易】页面，选择需要交易的币种——数字资产种类【USDT】或【BTC】后，根据自己的交易需求，在该页面根据自己的付款渠道（现金当面交易/FPS等）选择要交易的商家广告，点击【购买】进行下单。3️⃣ 点击【购买】后，填写需要购买的金额，并点击【0手续费买入USDT】即可生成买入订单，在订单页面点击【下一步】后按照页面显示的卖家收款账户进行转款，付款完成后需回到欧易订单页面点击【我已付款】并上传付款凭证，等待卖家确认收款放行数字资产即可完成交易。]]></description>
            <content:encoded><![CDATA[<p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chouyi.army/join/4722426">https://chouyi.army/join/4722426</a></p><p>1️⃣ 打开 App 首页，点击【我要买币】，选择【C2C买币】。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d1205c74dee43f1626747c7fd969548ab49ec0abfe17c6be5606da7aef74992e.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>2️⃣ 进入【C2C交易】页面，选择需要交易的币种——数字资产种类【USDT】或【BTC】后，根据自己的交易需求，在该页面根据自己的付款渠道（现金当面交易/FPS等）选择要交易的商家广告，点击【购买】进行下单。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c027d0f09451dd84091d29dd92cb0bb018c8eeb851b6b7e4c05d112d916eb451.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>3️⃣ 点击【购买】后，填写需要购买的金额，并点击【0手续费买入USDT】即可生成买入订单，在订单页面点击【下一步】后按照页面显示的卖家收款账户进行转款，付款完成后需回到欧易订单页面点击【我已付款】并上传付款凭证，等待卖家确认收款放行数字资产即可完成交易。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[欧易okx怎么购买USDT？欧易交易所买卖USDT全教程]]></title>
            <link>https://paragraph.com/@xiaoming/okx-usdt-usdt</link>
            <guid>WMur9AfL9C3ffQ8ZmlBG</guid>
            <pubDate>Tue, 24 Dec 2024 07:39:07 GMT</pubDate>
            <description><![CDATA[APP下载地址 1️⃣ 打开 App 首页，点击【我要买币】，选择【C2C买币】。2️⃣ 进入【C2C交易】页面，选择需要交易的币种——数字资产种类【USDT】或【BTC】后，根据自己的交易需求，在该页面根据自己的付款渠道（现金当面交易/FPS等）选择要交易的商家广告，点击【购买】进行下单。3️⃣ 点击【购买】后，填写需要购买的金额，并点击【0手续费买入USDT】即可生成买入订单，在订单页面点击【下一步】后按照页面显示的卖家收款账户进行转款，付款完成后需回到欧易订单页面点击【我已付款】并上传付款凭证，等待卖家确认收款放行数字资产即可完成交易。]]></description>
            <content:encoded><![CDATA[<p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://chouyi.army/join/4722426">APP下载地址</a></p><p>1️⃣ 打开 App 首页，点击【我要买币】，选择【C2C买币】。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/d1205c74dee43f1626747c7fd969548ab49ec0abfe17c6be5606da7aef74992e.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>2️⃣ 进入【C2C交易】页面，选择需要交易的币种——数字资产种类【USDT】或【BTC】后，根据自己的交易需求，在该页面根据自己的付款渠道（现金当面交易/FPS等）选择要交易的商家广告，点击【购买】进行下单。</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c027d0f09451dd84091d29dd92cb0bb018c8eeb851b6b7e4c05d112d916eb451.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>3️⃣ 点击【购买】后，填写需要购买的金额，并点击【0手续费买入USDT】即可生成买入订单，在订单页面点击【下一步】后按照页面显示的卖家收款账户进行转款，付款完成后需回到欧易订单页面点击【我已付款】并上传付款凭证，等待卖家确认收款放行数字资产即可完成交易。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[目前以太坊开发流行的开发工具和框架]]></title>
            <link>https://paragraph.com/@xiaoming/MkaD33dyvzjCwCNw5WEF</link>
            <guid>MkaD33dyvzjCwCNw5WEF</guid>
            <pubDate>Fri, 17 Feb 2023 00:46:15 GMT</pubDate>
            <description><![CDATA[当今以太坊开发中，有许多流行的开发工具和框架可供使用。以下是其中的一些：Remix：Remix是一种基于浏览器的以太坊IDE，可用于Solidity智能合约的编写、测试和部署。Truffle Suite：Truffle是一套以太坊开发工具，提供了一系列工具来快速开发、测试、部署以太坊智能合约，包括Truffle框架、Truffle Boxes、Truffle Teams等。Hardhat：Hardhat是一个用于以太坊开发的开发框架，提供了开发、测试、部署和调试以太坊智能合约的工具。Ganache：Ganache是一个基于以太坊的快速开发和测试区块链的本地区块链客户端。Web3.js：Web3.js是以太坊JavaScript API，可用于与以太坊网络进行交互。ethers.js：ethers.js是另一种以太坊JavaScript API，提供了许多与以太坊交互的功能，如智能合约的部署和交互等。OpenZeppelin：OpenZeppelin是一套用于以太坊智能合约的开源安全套件，其中包含了常用的智能合约安全模式和组件。这些开发工具和框架都能够帮助以太坊开发者更加高效、安全...]]></description>
            <content:encoded><![CDATA[<p>当今以太坊开发中，有许多流行的开发工具和框架可供使用。以下是其中的一些：</p><ol><li><p>Remix：Remix是一种基于浏览器的以太坊IDE，可用于Solidity智能合约的编写、测试和部署。</p></li><li><p>Truffle Suite：Truffle是一套以太坊开发工具，提供了一系列工具来快速开发、测试、部署以太坊智能合约，包括Truffle框架、Truffle Boxes、Truffle Teams等。</p></li><li><p>Hardhat：Hardhat是一个用于以太坊开发的开发框架，提供了开发、测试、部署和调试以太坊智能合约的工具。</p></li><li><p>Ganache：Ganache是一个基于以太坊的快速开发和测试区块链的本地区块链客户端。</p></li><li><p>Web3.js：Web3.js是以太坊JavaScript API，可用于与以太坊网络进行交互。</p></li><li><p>ethers.js：ethers.js是另一种以太坊JavaScript API，提供了许多与以太坊交互的功能，如智能合约的部署和交互等。</p></li><li><p>OpenZeppelin：OpenZeppelin是一套用于以太坊智能合约的开源安全套件，其中包含了常用的智能合约安全模式和组件。</p></li></ol><p>这些开发工具和框架都能够帮助以太坊开发者更加高效、安全地开发、测试和部署智能合约。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[android dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算]]></title>
            <link>https://paragraph.com/@xiaoming/android-dpi-dip-px-density</link>
            <guid>GpHSYLPXicwh4HYdaLtz</guid>
            <pubDate>Sun, 09 Jan 2022 12:02:03 GMT</pubDate>
            <description><![CDATA[一、基本概念 dip ： Density independent pixels ，设备无关像素。 dp ：就是dip px ： 像素 dpi ：dots per inch ， 直接来说就是一英寸多少个像素点。常见取值 120，160，240。我一般称作像素密度，简称密度 density ： 直接翻译的话貌似叫 密度。常见取值 1.5 ， 1.0 。和标准dpi的比例（160px/inc） 分辨率 ： 横纵2个方向的像素点的数量，常见取值 480X800 ，320X480 屏幕尺寸： 屏幕对角线的长度。电脑电视同理。 屏幕比例的问题。因为只确定了对角线长，2边长度还不一定。所以有了4：3、16：9这种，这样就可以算出屏幕边长了。 二、工具类实现public class DensityUtils { private DensityUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * dp转px * * @para...]]></description>
            <content:encoded><![CDATA[<p>一、基本概念</p><p>dip ： Density independent pixels ，设备无关像素。 dp ：就是dip px ： 像素 dpi ：dots per inch ， 直接来说就是一英寸多少个像素点。常见取值 120，160，240。我一般称作像素密度，简称密度 density ： 直接翻译的话貌似叫 密度。常见取值 1.5 ， 1.0 。和标准dpi的比例（160px/inc） 分辨率 ： 横纵2个方向的像素点的数量，常见取值 480X800 ，320X480 屏幕尺寸： 屏幕对角线的长度。电脑电视同理。 屏幕比例的问题。因为只确定了对角线长，2边长度还不一定。所以有了4：3、16：9这种，这样就可以算出屏幕边长了。</p><p>二、工具类实现</p><pre data-type="codeBlock" text="public class DensityUtils
{
    private DensityUtils()
    {  
        /* cannot be instantiated */
        throw new UnsupportedOperationException(&quot;cannot be instantiated&quot;);
    }

    /**
     * dp转px 
     *
     * @param context
     * @param val
     * @return
     */
    public static int dp2px(Context context, float dpVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, context.getResources().getDisplayMetrics());
    }

    /**
     * sp转px 
     *
     * @param context
     * @param val
     * @return
     */
    public static int sp2px(Context context, float spVal)
    {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, context.getResources().getDisplayMetrics());
    }

    /**
     * px转dp 
     *
     * @param context
     * @param pxVal
     * @return
     */
    public static float px2dp(Context context, float pxVal)
    {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (pxVal / scale);
    }

    /**
     * px转sp 
     *
     * @param fontScale
     * @param pxVal
     * @return
     */
    public static float px2sp(Context context, float pxVal)
    {
        return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
    }
"><code><span class="hljs-keyword">public</span> class DensityUtils
{
    <span class="hljs-keyword">private</span> DensityUtils()
    {  
        <span class="hljs-comment">/* cannot be instantiated */</span>
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnsupportedOperationException(<span class="hljs-string">"cannot be instantiated"</span>);
    }

    <span class="hljs-comment">/**
     * dp转px 
     *
     * @param context
     * @param val
     * @return
     */</span>
    <span class="hljs-keyword">public</span> static <span class="hljs-keyword">int</span> dp2px(Context context, float dpVal)
    {
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dpVal, context.getResources().getDisplayMetrics());
    }

    <span class="hljs-comment">/**
     * sp转px 
     *
     * @param context
     * @param val
     * @return
     */</span>
    <span class="hljs-keyword">public</span> static <span class="hljs-keyword">int</span> sp2px(Context context, float spVal)
    {
        <span class="hljs-keyword">return</span> (<span class="hljs-keyword">int</span>) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                spVal, context.getResources().getDisplayMetrics());
    }

    <span class="hljs-comment">/**
     * px转dp 
     *
     * @param context
     * @param pxVal
     * @return
     */</span>
    <span class="hljs-keyword">public</span> static float px2dp(Context context, float pxVal)
    {
        final float scale <span class="hljs-operator">=</span> context.getResources().getDisplayMetrics().density;
        <span class="hljs-keyword">return</span> (pxVal <span class="hljs-operator">/</span> scale);
    }

    <span class="hljs-comment">/**
     * px转sp 
     *
     * @param fontScale
     * @param pxVal
     * @return
     */</span>
    <span class="hljs-keyword">public</span> static float px2sp(Context context, float pxVal)
    {
        <span class="hljs-keyword">return</span> (pxVal <span class="hljs-operator">/</span> context.getResources().getDisplayMetrics().scaledDensity);
    }
</code></pre>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[Android retrofit的简单封装]]></title>
            <link>https://paragraph.com/@xiaoming/android-retrofit</link>
            <guid>YfUmc9kehHCptfRH0vIR</guid>
            <pubDate>Sun, 09 Jan 2022 12:01:34 GMT</pubDate>
            <description><![CDATA[1.Retrofit是基于OkHttp网络请求框架的二次封装而已，懂Okhttp的小伙伴，那么Retrofit也就基本都会。 2.Retrofit采用注解配置请求的方式： 3.性能最好，处理最快 4.使用REST API时非常方便； 5.传输层默认就使用OkHttp； 6.支持NIO； 7.拥有出色的API文档和社区支持 8.速度上比volley更快； 9.如果你的应用程序中集成了OKHttp，Retrofit默认会使用OKHttp处理其他网络层请求。 10.默认使用Gson一：retrofit的使用Retrofit支持同步和异步两种方式，在使用时，需要将请求地址转换为接口，通过注解来指定请求方法，请求参数，请求头，返回值等信息。get请求到服务器后从数据库查询数据，返回值为查询到的数据，post请求向服务器提交一条数据，返回值为提交的数据。一：首先完成请求所用的service，是一个interface，完全通过注解完成配置。 倚赖需要的包 compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.google.co...]]></description>
            <content:encoded><![CDATA[<blockquote><p>1.Retrofit是基于OkHttp网络请求框架的二次封装而已，懂Okhttp的小伙伴，那么Retrofit也就基本都会。 2.Retrofit采用注解配置请求的方式： 3.性能最好，处理最快 4.使用REST API时非常方便； 5.传输层默认就使用OkHttp； 6.支持NIO； 7.拥有出色的API文档和社区支持 8.速度上比volley更快； 9.如果你的应用程序中集成了OKHttp，Retrofit默认会使用OKHttp处理其他网络层请求。 10.默认使用Gson</p></blockquote><h4 id="h-retrofit" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">一：retrofit的使用</h4><blockquote><p>Retrofit支持同步和异步两种方式，在使用时，需要将请求地址转换为接口，通过注解来指定请求方法，请求参数，请求头，返回值等信息。get请求到服务器后从数据库查询数据，返回值为查询到的数据，post请求向服务器提交一条数据，返回值为提交的数据。</p></blockquote><p>一：首先完成请求所用的service，是一个interface，完全通过注解完成配置。</p><p>倚赖需要的包</p><pre data-type="codeBlock" text="   compile &apos;com.squareup.retrofit2:retrofit:2.1.0&apos;
   compile &apos;com.google.code.gson:gson:2.8.0&apos;
"><code>   <span class="hljs-built_in">compile</span> <span class="hljs-string">'com.squareup.retrofit2:retrofit:2.1.0'</span>
   <span class="hljs-built_in">compile</span> <span class="hljs-string">'com.google.code.gson:gson:2.8.0'</span>
</code></pre><pre data-type="codeBlock" text="
public interface DouBanApiClient {

    /**
     *@param headers  请求参数头
     *@param url   请求的地址
     *@param params 请求的参数
     */
    @GET()
    Call&lt;ResponseBody&gt; get(@HeaderMap Map&lt;String, String&gt; headers, @Url String url, @QueryMap Map&lt;String, String&gt; params);

    @FormUrlEncoded
    @POST()
    Call&lt;String&gt; post(@HeaderMap Map&lt;String, String&gt; headers, @Url String url, @FieldMap Map&lt;String, String&gt; params);

    @Streaming
    @GET()
    Call&lt;ResponseBody&gt; download(@HeaderMap Map&lt;String, String&gt; headers, @Url String url, @QueryMap Map&lt;String, String&gt; params);
}
"><code>
<span class="hljs-selector-tag">public</span> <span class="hljs-selector-tag">interface</span> <span class="hljs-selector-tag">DouBanApiClient</span> {

    <span class="hljs-comment">/**
     *@param headers  请求参数头
     *@param url   请求的地址
     *@param params 请求的参数
     */</span>
    <span class="hljs-variable">@GET</span>()
    Call&#x3C;ResponseBody> <span class="hljs-built_in">get</span>(<span class="hljs-variable">@HeaderMap</span> Map&#x3C;String, String> headers, <span class="hljs-variable">@Url</span> String url, <span class="hljs-variable">@QueryMap</span> Map&#x3C;String, String> params);

    <span class="hljs-variable">@FormUrlEncoded</span>
    <span class="hljs-variable">@POST</span>()
    Call&#x3C;String> <span class="hljs-built_in">post</span>(<span class="hljs-variable">@HeaderMap</span> Map&#x3C;String, String> headers, <span class="hljs-variable">@Url</span> String url, <span class="hljs-variable">@FieldMap</span> Map&#x3C;String, String> params);

    <span class="hljs-variable">@Streaming</span>
    <span class="hljs-variable">@GET</span>()
    Call&#x3C;ResponseBody> <span class="hljs-built_in">download</span>(<span class="hljs-variable">@HeaderMap</span> Map&#x3C;String, String> headers, <span class="hljs-variable">@Url</span> String url, <span class="hljs-variable">@QueryMap</span> Map&#x3C;String, String> params);
}
</code></pre><p>二：创建一个请求单例 ApiClient，方便管理网络请求，本文只给出get请求的实现方式。</p><p>（ApiBuilder 构建的参数 包含 请求 url header params，后文会贴出代码）</p><pre data-type="codeBlock" text="/**
 *
 * 网络请求类
 * Created by Administrator on 2017/2/13 0013.
 */

public class ApiClient {

    static ApiClient instance;


    public final static  String BASE_API = &quot;http://app.youxiake.com&quot;;

    /**
     * 请求的接口
     * */
    public static String Api_BookInfo = &quot;/api/discover/list/hot&quot;;


    /***
     *
     * 构建 retrofit请求
     * */
    private final static Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(ApiClient.BASE_API)
            .build();


    /**
     * 获得 DouBanApiClient实例
     * @return
     */
    public DouBanApiClient getDbService(){

        return retrofit.create(DouBanApiClient.class);
    }

    /**
     * 创建请求单例
     * @return
     */
    public static ApiClient getInstance(){

        if(instance == null){
            synchronized (ApiClient.class){
                if(instance ==null){
                    instance = new ApiClient();
                }
            }
        }
        return instance;
    }



    /**
     *
     * get请求
     * @param builder  request构建的参数 包含 url header params
     * @param onCallback  rquest 回调
     * @param classOf   指定请求的model类型
     * @param &lt;T&gt;
     */
    public &lt;T&gt; void doGet(ApiBuilder builder ,final com.retrofitdemo.interfaces.CallBack&lt;T&gt; onCallback,final Class classOf){

        DouBanApiClient dbService = getDbService();
        Call&lt;ResponseBody&gt; stringCall = dbService.get(checkHeaders(builder.headers),
                checkUrl(builder.url), checkParams(builder.params));

        stringCall.enqueue(new Callback&lt;ResponseBody&gt;() {
            @Override
            public void onResponse(Call&lt;ResponseBody&gt; call, Response&lt;ResponseBody&gt; response) {

                Object o = null;
                try {
                    Log.d(&quot;TAG&quot;,&quot;----&quot;+response.body().string());
                    o = new Gson().fromJson(response.body().string(), classOf);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                onCallback.onSuccess(call, (T) o);
            }

            @Override
            public void onFailure(Call&lt;ResponseBody&gt; call, Throwable t) {
                onCallback.onFailure(call,t);
                Log.d(&quot;TAG&quot;,&quot;----&quot;+t.getMessage());
            }
        });
    }



    private String checkUrl(String url) {
        if (checkNULL(url)) {

            return null;
        }
        return url;
    }
    // 判断是否NULL
    public static boolean checkNULL(String str) {
        return str == null || &quot;null&quot;.equals(str) || &quot;&quot;.equals(str);

    }

    // 判断是否NULL
    public static void Error(Context context, String msg) {
        if (checkNULL(msg)) {
            msg = &quot;未知异常&quot;;
        }
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
    }

    public static Map&lt;String, String&gt; checkHeaders(Map&lt;String, String&gt; headers) {
        if (headers == null) {
            headers = new HashMap&lt;&gt;();
        }
        //retrofit的headers的值不能为null，此处做下校验，防止出错
        for (Map.Entry&lt;String, String&gt; entry : headers.entrySet()) {
            if (entry.getValue() == null) {
                headers.put(entry.getKey(), &quot;&quot;);
            }
        }
        return headers;
    }

    public static Map&lt;String, String&gt; checkParams(Map&lt;String, String&gt; params) {
        if (params == null) {
            params = new HashMap&lt;&gt;();
        }
        //retrofit的params的值不能为null，此处做下校验，防止出错
        for (Map.Entry&lt;String, String&gt; entry : params.entrySet()) {
            if (entry.getValue() == null) {
                params.put(entry.getKey(), &quot;&quot;);
            }
        }
        return params;
    }
}
"><code><span class="hljs-comment">/**
 *
 * 网络请求类
 * Created by Administrator on 2017/2/13 0013.
 */</span>

<span class="hljs-keyword">public</span> class ApiClient {

    static ApiClient instance;


    <span class="hljs-keyword">public</span> final static  String BASE_API <span class="hljs-operator">=</span> <span class="hljs-string">"http://app.youxiake.com"</span>;

    <span class="hljs-comment">/**
     * 请求的接口
     * */</span>
    <span class="hljs-keyword">public</span> static String Api_BookInfo <span class="hljs-operator">=</span> <span class="hljs-string">"/api/discover/list/hot"</span>;


    <span class="hljs-comment">/***
     *
     * 构建 retrofit请求
     * */</span>
    <span class="hljs-keyword">private</span> final static Retrofit retrofit <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Retrofit.Builder()
            .baseUrl(ApiClient.BASE_API)
            .build();


    <span class="hljs-comment">/**
     * 获得 DouBanApiClient实例
     * @return
     */</span>
    <span class="hljs-keyword">public</span> DouBanApiClient getDbService(){

        <span class="hljs-keyword">return</span> retrofit.create(DouBanApiClient.class);
    }

    <span class="hljs-comment">/**
     * 创建请求单例
     * @return
     */</span>
    <span class="hljs-keyword">public</span> static ApiClient getInstance(){

        <span class="hljs-keyword">if</span>(instance <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null){
            synchronized (ApiClient.class){
                <span class="hljs-keyword">if</span>(instance <span class="hljs-operator">=</span><span class="hljs-operator">=</span>null){
                    instance <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ApiClient();
                }
            }
        }
        <span class="hljs-keyword">return</span> instance;
    }



    <span class="hljs-comment">/**
     *
     * get请求
     * @param builder  request构建的参数 包含 url header params
     * @param onCallback  rquest 回调
     * @param classOf   指定请求的model类型
     * @param &#x3C;T>
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-operator">&#x3C;</span>T<span class="hljs-operator">></span> void doGet(ApiBuilder builder ,final com.retrofitdemo.interfaces.CallBack&#x3C;T<span class="hljs-operator">></span> onCallback,final Class classOf){

        DouBanApiClient dbService <span class="hljs-operator">=</span> getDbService();
        Call<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> stringCall <span class="hljs-operator">=</span> dbService.get(checkHeaders(builder.headers),
                checkUrl(builder.url), checkParams(builder.params));

        stringCall.enqueue(<span class="hljs-keyword">new</span> Callback<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span>() {
            @Override
            <span class="hljs-keyword">public</span> void onResponse(Call<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> call, Response<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> response) {

                Object o <span class="hljs-operator">=</span> null;
                <span class="hljs-keyword">try</span> {
                    Log.d(<span class="hljs-string">"TAG"</span>,<span class="hljs-string">"----"</span><span class="hljs-operator">+</span>response.body().string());
                    o <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> Gson().fromJson(response.body().string(), classOf);
                } <span class="hljs-keyword">catch</span> (IOException e) {
                    e.printStackTrace();
                }

                onCallback.onSuccess(call, (T) o);
            }

            @Override
            <span class="hljs-keyword">public</span> void onFailure(Call<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> call, Throwable t) {
                onCallback.onFailure(call,t);
                Log.d(<span class="hljs-string">"TAG"</span>,<span class="hljs-string">"----"</span><span class="hljs-operator">+</span>t.getMessage());
            }
        });
    }



    <span class="hljs-keyword">private</span> String checkUrl(String url) {
        <span class="hljs-keyword">if</span> (checkNULL(url)) {

            <span class="hljs-keyword">return</span> null;
        }
        <span class="hljs-keyword">return</span> url;
    }
    <span class="hljs-comment">// 判断是否NULL</span>
    <span class="hljs-keyword">public</span> static boolean checkNULL(String str) {
        <span class="hljs-keyword">return</span> str <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-string">"null"</span>.equals(str) <span class="hljs-operator">|</span><span class="hljs-operator">|</span> <span class="hljs-string">""</span>.equals(str);

    }

    <span class="hljs-comment">// 判断是否NULL</span>
    <span class="hljs-keyword">public</span> static void <span class="hljs-built_in">Error</span>(Context context, String <span class="hljs-built_in">msg</span>) {
        <span class="hljs-keyword">if</span> (checkNULL(<span class="hljs-built_in">msg</span>)) {
            <span class="hljs-built_in">msg</span> <span class="hljs-operator">=</span> <span class="hljs-string">"未知异常"</span>;
        }
        Toast.makeText(context, <span class="hljs-built_in">msg</span>, Toast.LENGTH_SHORT).show();
    }

    <span class="hljs-keyword">public</span> static Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> checkHeaders(Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> headers) {
        <span class="hljs-keyword">if</span> (headers <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
            headers <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> HashMap<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">></span>();
        }
        <span class="hljs-comment">//retrofit的headers的值不能为null，此处做下校验，防止出错</span>
        <span class="hljs-keyword">for</span> (Map.Entry&#x3C;String, String<span class="hljs-operator">></span> entry : headers.entrySet()) {
            <span class="hljs-keyword">if</span> (entry.getValue() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
                headers.put(entry.getKey(), <span class="hljs-string">""</span>);
            }
        }
        <span class="hljs-keyword">return</span> headers;
    }

    <span class="hljs-keyword">public</span> static Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> checkParams(Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> params) {
        <span class="hljs-keyword">if</span> (params <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
            params <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> HashMap<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">></span>();
        }
        <span class="hljs-comment">//retrofit的params的值不能为null，此处做下校验，防止出错</span>
        <span class="hljs-keyword">for</span> (Map.Entry&#x3C;String, String<span class="hljs-operator">></span> entry : params.entrySet()) {
            <span class="hljs-keyword">if</span> (entry.getValue() <span class="hljs-operator">=</span><span class="hljs-operator">=</span> null) {
                params.put(entry.getKey(), <span class="hljs-string">""</span>);
            }
        }
        <span class="hljs-keyword">return</span> params;
    }
}
</code></pre><p>三：构建请求的参数</p><pre data-type="codeBlock" text="
/**
 * Created by cvmars 2017/2/14 0014.
 */

public class ApiBuilder {

    Map&lt;String, String&gt; params ;
    Map&lt;String, String&gt; headers ;
    String url;

    public ApiBuilder Params(Map&lt;String, String&gt; params) {
        this.params.putAll(params);
        return this;
    }

    public ApiBuilder Params(String key, String value) {
        this.params.put(key, value);
        return this;
    }

    public ApiBuilder Headers(Map&lt;String, String&gt; headers) {
        this.headers.putAll(headers);
        return this;
    }

    public ApiBuilder Headers(String key, String value) {
        this.headers.put(key, value);
        return this;
    }

    public ApiBuilder Url(String url) {
        this.url = url;
        return this;
    }

    public ApiBuilder(String url) {
        this.setParams(url);
    }

    public ApiBuilder() {
        this.setParams(null);
    }


    private void setParams(String url) {
        this.url = url;
        this.params = new HashMap&lt;&gt;();
        this.headers = new HashMap&lt;&gt;();
    }
}
"><code>
<span class="hljs-comment">/**
 * Created by cvmars 2017/2/14 0014.
 */</span>

<span class="hljs-keyword">public</span> class ApiBuilder {

    Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> params ;
    Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> headers ;
    String url;

    <span class="hljs-keyword">public</span> ApiBuilder Params(Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> params) {
        <span class="hljs-built_in">this</span>.params.putAll(params);
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }

    <span class="hljs-keyword">public</span> ApiBuilder Params(String key, String value) {
        <span class="hljs-built_in">this</span>.params.put(key, value);
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }

    <span class="hljs-keyword">public</span> ApiBuilder Headers(Map<span class="hljs-operator">&#x3C;</span>String, String<span class="hljs-operator">></span> headers) {
        <span class="hljs-built_in">this</span>.headers.putAll(headers);
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }

    <span class="hljs-keyword">public</span> ApiBuilder Headers(String key, String value) {
        <span class="hljs-built_in">this</span>.headers.put(key, value);
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }

    <span class="hljs-keyword">public</span> ApiBuilder Url(String url) {
        <span class="hljs-built_in">this</span>.url <span class="hljs-operator">=</span> url;
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }

    <span class="hljs-keyword">public</span> ApiBuilder(String url) {
        <span class="hljs-built_in">this</span>.setParams(url);
    }

    <span class="hljs-keyword">public</span> ApiBuilder() {
        <span class="hljs-built_in">this</span>.setParams(null);
    }


    <span class="hljs-keyword">private</span> void setParams(String url) {
        <span class="hljs-built_in">this</span>.url <span class="hljs-operator">=</span> url;
        <span class="hljs-built_in">this</span>.params <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> HashMap<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">></span>();
        <span class="hljs-built_in">this</span>.headers <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> HashMap<span class="hljs-operator">&#x3C;</span><span class="hljs-operator">></span>();
    }
}
</code></pre><p>四：回调接口</p><pre data-type="codeBlock" text="
public interface CallBack&lt;T&gt; {

    void onSuccess(Call&lt;ResponseBody&gt; call, T response);

    void onFailure(Call&lt;ResponseBody&gt; call, Throwable t);
}
"><code>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">CallBack</span>&#x3C;<span class="hljs-title">T</span>> {

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onSuccess</span>(<span class="hljs-params">Call&#x3C;ResponseBody> call, T response</span>)</span>;

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onFailure</span>(<span class="hljs-params">Call&#x3C;ResponseBody> call, Throwable t</span>)</span>;
}
</code></pre><p>五：简单的封装基本完成：下面是基本使用方法</p><p>先创建返回的model</p><pre data-type="codeBlock" text="public class FindContent {

    
    public String msg;
    public int code;

    public DataBean data;

    public static class DataBean {
        public int total;
        public int totalPage;
        public int pageSize;

        public List&lt;QuotesListBean&gt; quotesList;

        public static class QuotesListBean {
            public String content;
            public String uid;
            public String address;
            public String show_address;
            public String comment;
            public String prise;
            public String gmt_create;
            public String type;
            public String video;
            public Object activity;
            public String username;
            public String avatar;
            public int quote_id;
            public String relation;
            public String share_url;
            public boolean prised;
            public List&lt;ImagesBean&gt; images;
            public List&lt;?&gt; discus;

            public static class ImagesBean {
                public String width;
                public String height;
                public String url;
                public String url_xl;
                public String url_l;
                public String url_m;
                public List&lt;?&gt; labels_info;
            }
        }
    }
}
"><code>public class FindContent {

    
    public String msg<span class="hljs-comment">;</span>
    public int code<span class="hljs-comment">;</span>

    public DataBean data<span class="hljs-comment">;</span>

    public static class DataBean {
        public int total<span class="hljs-comment">;</span>
        public int totalPage<span class="hljs-comment">;</span>
        public int pageSize<span class="hljs-comment">;</span>

        public List&#x3C;QuotesListBean> quotesList<span class="hljs-comment">;</span>

        public static class QuotesListBean {
            public String content<span class="hljs-comment">;</span>
            public String uid<span class="hljs-comment">;</span>
            public String address<span class="hljs-comment">;</span>
            public String show_address<span class="hljs-comment">;</span>
            public String comment<span class="hljs-comment">;</span>
            public String prise<span class="hljs-comment">;</span>
            public String gmt_create<span class="hljs-comment">;</span>
            public String type<span class="hljs-comment">;</span>
            public String video<span class="hljs-comment">;</span>
            public Object activity<span class="hljs-comment">;</span>
            public String username<span class="hljs-comment">;</span>
            public String avatar<span class="hljs-comment">;</span>
            public int quote_id<span class="hljs-comment">;</span>
            public String relation<span class="hljs-comment">;</span>
            public String share_url<span class="hljs-comment">;</span>
            public boolean prised<span class="hljs-comment">;</span>
            public List&#x3C;ImagesBean> images<span class="hljs-comment">;</span>
            public List&#x3C;?> discus<span class="hljs-comment">;</span>

            public static class ImagesBean {
                public String width<span class="hljs-comment">;</span>
                public String height<span class="hljs-comment">;</span>
                public String url<span class="hljs-comment">;</span>
                public String url_xl<span class="hljs-comment">;</span>
                public String url_l<span class="hljs-comment">;</span>
                public String url_m<span class="hljs-comment">;</span>
                public List&#x3C;?> labels_info<span class="hljs-comment">;</span>
            }
        }
    }
}
</code></pre><p>在需要请求的地方进行调用</p><pre data-type="codeBlock" text="
    ApiBuilder builder = new ApiBuilder(ApiClient.Api_BookInfo)
                .Headers(&quot;header1&quot;,&quot;this is request header&quot;)
                .Headers(&quot;header2&quot;,&quot;this is request header2&quot;)
                .Params(&quot;params&quot;,&quot;this is request params&quot;);
        ApiClient.getInstance().doGet(builder, new CallBack&lt;FindContent&gt;() {
            @Override
            public void onSuccess(Call&lt;ResponseBody&gt; call, FindContent response) {

                mContent.setText(response.toString());
            }
            @Override
            public void onFailure(Call&lt;ResponseBody&gt; call, Throwable t) {


            }
        },FindContent.class);
    }
"><code>
    ApiBuilder builder <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> ApiBuilder(ApiClient.Api_BookInfo)
                .Headers(<span class="hljs-string">"header1"</span>,<span class="hljs-string">"this is request header"</span>)
                .Headers(<span class="hljs-string">"header2"</span>,<span class="hljs-string">"this is request header2"</span>)
                .Params(<span class="hljs-string">"params"</span>,<span class="hljs-string">"this is request params"</span>);
        ApiClient.getInstance().doGet(builder, <span class="hljs-keyword">new</span> CallBack<span class="hljs-operator">&#x3C;</span>FindContent<span class="hljs-operator">></span>() {
            @Override
            <span class="hljs-keyword">public</span> void onSuccess(Call<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> call, FindContent response) {

                mContent.setText(response.toString());
            }
            @Override
            <span class="hljs-keyword">public</span> void onFailure(Call<span class="hljs-operator">&#x3C;</span>ResponseBody<span class="hljs-operator">></span> call, Throwable t) {


            }
        },FindContent.class);
    }
</code></pre>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[以太坊开发（一）——Truffle和Ganache]]></title>
            <link>https://paragraph.com/@xiaoming/truffle-ganache</link>
            <guid>psfwjnuBP9SRZ1MxnB2a</guid>
            <pubDate>Sun, 09 Jan 2022 12:00:25 GMT</pubDate>
            <description><![CDATA[ruffle是目前最流行的以太坊开发框架，采用JavaScript编写，支持智能合约的编译、部署和测试。 一、安装Truffle首先安装Truffle依赖的NodeJS：curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash - sudo apt-get install -y nodejs sudo apt-get install npmsudo npm config set registry http://registry.npm.taobao.org安装Trufflesudo npm install -g truffle 二、创建工程 如果想创建一个空工程，可以用下面的命令： truffle init 在早期版本的truffle中，刚刚创建的工程中还会包含metacoin的示例代码。新版本truffle引入了box的概念，所有的示例代码都以box的形式提供。因此我们不需要用truffle init命令，用下面的命令就可以直接下载metacoin的示例代码： truffle unbox metacoin 代码结构...]]></description>
            <content:encoded><![CDATA[<p>ruffle是目前最流行的以太坊开发框架，采用JavaScript编写，支持智能合约的编译、部署和测试。</p><p>一、安装Truffle</p><ol><li><p>首先安装Truffle依赖的NodeJS：</p></li></ol><p>curl -sL <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://deb.nodesource.com/setup_9.x">https://deb.nodesource.com/setup_9.x</a> | sudo -E bash -</p><p>sudo apt-get install -y nodejs</p><p>sudo apt-get install npm</p><pre data-type="codeBlock" text="配置npm源为国内源（可选，可加快下载速度）：
"><code></code></pre><p>sudo npm config set registry <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://registry.npm.taobao.org">http://registry.npm.taobao.org</a></p><ol><li><p>安装Truffle</p></li></ol><p>sudo npm install -g truffle</p><p>二、创建工程</p><p>如果想创建一个空工程，可以用下面的命令：</p><p>truffle init</p><p>在早期版本的truffle中，刚刚创建的工程中还会包含metacoin的示例代码。新版本truffle引入了box的概念，所有的示例代码都以box的形式提供。因此我们不需要用truffle init命令，用下面的命令就可以直接下载metacoin的示例代码：</p><p>truffle unbox metacoin</p><p>代码结构如下图所示：</p><p>主要分为3个部分：</p><p>● contracts目录中包含Solidity合约代码，其中Migrations.sol是必须的，其他就是你自己写的合约代码了。</p><p>● migrations目录中包含合约部署脚本，其中1_initial_migration.js就是用来部署Migrations.sol的，其他的脚本会按照顺序依次执行。</p><p>● test目录中就是测试代码了。</p><p>三、安装以太坊客户端</p><p>智能合约必须要部署到链上进行测试。可以选择部署到一些公共的测试链比如Rinkeby或者Ropsten上，缺点是部署和测试时间比较长，而且需要花费一定的时间赚取假代币防止out of gas。</p><p>还有一种方式就是部署到私链上，Truffle官方推荐使用以下两种客户端：</p><p>● Ganache</p><p>● truffle develop</p><ol><li><p>Ganache</p></li></ol><p>Ganache这个名字比较陌生，但是它的前身testRPC却是大名鼎鼎，网上的很多老文章里都是用testRPC。Ganache是奶油巧克力的意思，据说是很久之前有个学徒做巧克力的放多了牛奶，师傅正要骂他，结果一尝发现味道还真不错，于是一种新的巧克力就诞生了~ Truffle是松露巧克力，一般是以Ganache为核，然后上面撒上可可粉，所以这两个产品的名字还是很贴切的。</p><p>Ganache现在有两个版本，一个是带图形界面的版本，下载地址：</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/trufflesuite/ganache/releases">https://github.com/trufflesuite/ganache/releases</a></p><p>这些可执行文件的后缀都比较奇葩，参见下面的对应关系：</p><p>● Windows: Ganache-*.appx</p><p>● Mac: Ganache-*.dmg</p><p>● Linux: Ganache-*.AppImage</p><p>还有一个就是命令行版本了，下载方法：</p><p>sudo npm install -g ganache-cli</p><p>具体的命令行参数配置参见github：</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/trufflesuite/ganache-cli">https://github.com/trufflesuite/ganache-cli</a></p><p>本文采用带图形界面的Ganache版本。</p><ol><li><p>truffle develop</p></li></ol><p>这个是truffle内置的客户端，跟命令行版本的Ganache基本类似。唯一要注意的是在truffle develop里执行truffle命令的时候需要省略前面的“truffle”，比如“truffle compile”只需要敲“compile”就可以了。</p><p>四、编译和部署合约</p><p>Ganache默认运行在7545端口，可以在界面右上方的“设置”里进行更改。运行后默认创建10个账号，每个账号里有100ETH的余额。</p><p>要部署到链上，需要把IP、端口、网络ID告诉truffle。修改truffle.js：</p><p>module.exports = {</p><pre data-type="codeBlock" text="networks: {

    development: {

        host: &apos;localhost&apos;,

        port: &apos;7545&apos;,

        network_id: &apos;*&apos; // Match any network id

    }

}
"><code>networks: {

    development: {

        host: <span class="hljs-string">'localhost'</span>,

        port: <span class="hljs-string">'7545'</span>,

        network_id: <span class="hljs-string">'*'</span> // Match any network id

    }

}
</code></pre><p>};</p><p>然用下面两条命令编译和部署：</p><p>truffle compile</p><p>truffle migrate</p><p>五、测试合约</p><p>metacoin的示例代码里已经把测试代码写好了，直接用下面的命令运行就可以了：</p><p>truffle test</p><p>去Ganache上看一下运行结果：</p><p>● Accounts标签：第一个账户里ETH略有减少，因为交易消耗了gas</p><p>● Blocks标签：Ganache是自动挖矿，生成了6个新区块，每个区块里有一个交易</p><p>● Transactions标签：有6笔新交易，可以点开看交易详情</p><p>● Logs标签：显示交易和挖矿日志</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[从数据结构上看比特币]]></title>
            <link>https://paragraph.com/@xiaoming/Ll4bu6qjqzdaKpWgZUL7</link>
            <guid>Ll4bu6qjqzdaKpWgZUL7</guid>
            <pubDate>Sun, 09 Jan 2022 11:59:50 GMT</pubDate>
            <description><![CDATA[比特币谈论区块链的人越来越多了，区块链算法本身是一种分布式存储模型，专门用于解决记账问题的算法。因为其去中心化，还有不改特性。可以做到通过数学和密码学解决现实生活中的信任问题。看了很多关于区块链和比特币的文章，我们不如通过代码来读比特币更靠谱点！ 就好像我们做个游戏，没有人关系你用什么语言写的、用什么服务器、服务器性能怎么样。人们只关心这个游戏好不好用。无论你的代码写得多好，系统架构是怎样的，硬件或者模型设计多优化，用了多么高科技的技术，但只要游戏做的不好就是一个废品。 ###区块链实际上是解决中心记账问题的一个模型### ####传统记账模式#### 以腾讯为例，腾讯自己有个审计部门，省级有审计部门，市级有审计部门。腾讯每天有大量的订单产生，同样审计部门有无数的账单产生，腾讯财务发送账单到市级 ，然后市级在发到省级，省级在反馈到市级再到腾讯。数据量很小的时候，各级部门都能审计，但当订单越做越大时候，如果有人做假账或者漏了某笔账单，基本上就是一笔烂账了。不管管理体系做得多好，想要查出来被修改的错误账单，基本都是不可能的。 ####比特币记账模式### #####先列出最简单的区块...]]></description>
            <content:encoded><![CDATA[<p>比特币谈论区块链的人越来越多了，区块链算法本身是一种分布式存储模型，专门用于解决记账问题的算法。因为其去中心化，还有不改特性。可以做到通过数学和密码学解决现实生活中的信任问题。看了很多关于区块链和比特币的文章，我们不如通过代码来读比特币更靠谱点！</p><p>就好像我们做个游戏，没有人关系你用什么语言写的、用什么服务器、服务器性能怎么样。人们只关心这个游戏好不好用。无论你的代码写得多好，系统架构是怎样的，硬件或者模型设计多优化，用了多么高科技的技术，但只要游戏做的不好就是一个废品。</p><p>###区块链实际上是解决中心记账问题的一个模型###</p><p>####传统记账模式####</p><p>以腾讯为例，腾讯自己有个审计部门，省级有审计部门，市级有审计部门。腾讯每天有大量的订单产生，同样审计部门有无数的账单产生，腾讯财务发送账单到市级 ，然后市级在发到省级，省级在反馈到市级再到腾讯。数据量很小的时候，各级部门都能审计，但当订单越做越大时候，如果有人做假账或者漏了某笔账单，基本上就是一笔烂账了。不管管理体系做得多好，想要查出来被修改的错误账单，基本都是不可能的。</p><p>####比特币记账模式###</p><p>#####先列出最简单的区块链数据结构代码#####</p><pre data-type="codeBlock" text="
//区块

type Block struct{

//时间戳

Timestamp int64;

//账单数据

Date []byte;

//前一个区块的hash值

PrevBlockHash  []byte;

//哈希值

Hash []byte;

}
"><code>
<span class="hljs-comment">//区块</span>

<span class="hljs-keyword">type</span> Block <span class="hljs-keyword">struct</span>{

<span class="hljs-comment">//时间戳</span>

Timestamp <span class="hljs-type">int64</span>;

<span class="hljs-comment">//账单数据</span>

Date []<span class="hljs-type">byte</span>;

<span class="hljs-comment">//前一个区块的hash值</span>

PrevBlockHash  []<span class="hljs-type">byte</span>;

<span class="hljs-comment">//哈希值</span>

Hash []<span class="hljs-type">byte</span>;

}
</code></pre><p>###变量分析###</p><p>1.时间戳：当前区块生成的时间</p><p>2.账单数据：打包的数据</p><p>3.PrevBlockHash ：前一个区块的hash值（地址或者唯一表示那个区块的地址，比如人的身份证）</p><ol><li><p>Hash ：当前区块的hash值</p></li></ol><h5 id="h-data" class="text-lg font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Data这里并不是真的账单，而是一个默克尔树的根节点的校验值</h5><p>后面加上默克尔树，再重新理解一下区块链 #####</p><pre data-type="codeBlock" text="
//区块
type Block struct{
//块头
Head BlockHead;
// 账单数据

Data Merkle

}

//块头
type BlockHead struct{
//时间戳

Timestamp int64;

//前一个区块的hash值

PrevBlockHash  []byte;

//哈希值

Hash []byte;

}

//账单数据

type Merkle struct{

//每一条交易记录
Data []byte;

}
"><code>
<span class="hljs-comment">//区块</span>
<span class="hljs-keyword">type</span> Block <span class="hljs-keyword">struct</span>{
<span class="hljs-comment">//块头</span>
Head BlockHead;
<span class="hljs-comment">// 账单数据</span>

Data Merkle

}

<span class="hljs-comment">//块头</span>
<span class="hljs-keyword">type</span> BlockHead <span class="hljs-keyword">struct</span>{
<span class="hljs-comment">//时间戳</span>

Timestamp <span class="hljs-type">int64</span>;

<span class="hljs-comment">//前一个区块的hash值</span>

PrevBlockHash  []<span class="hljs-type">byte</span>;

<span class="hljs-comment">//哈希值</span>

Hash []<span class="hljs-type">byte</span>;

}

<span class="hljs-comment">//账单数据</span>

<span class="hljs-keyword">type</span> Merkle <span class="hljs-keyword">struct</span>{

<span class="hljs-comment">//每一条交易记录</span>
Data []<span class="hljs-type">byte</span>;

}
</code></pre><p>上面这个Merkle参数，默克尔树可以理解为就是一个账单。还是刚才的阶段一，每一个Data不是一条交易记录，可以理解为一个块记录就是一个账单。</p><p>当交易记录太多的时候，记账的交易数据量太大了，将整个账单参与Hash值的计算，运算量太大，太麻烦了，所以用Merkle树的方式记账。</p><p>关于默克尔树就不讲太多了，有兴趣的可以去查一下，跟区块链其实很像，其中每一个树节点都是这个树节点的子节点的Hash校验值计算出来的。</p><p>简单一点理解，可以认为通过Merkle树的方式做了一个账单，这个账单有一个根节点，这里记做MerkleRoot，是树结构的一个节点，不明白的还可以理解为一个校验数字。整个账单里只要有任何一个字节对不上，都会导致MerkleRoot这个数字产生变化，所以一旦这个账单做好了之后，将Merkle账单的MerkleRoot这个数字写入到区块头里面，那么整个账单的任何一个字都不能修改，一旦有任何修改，都会导致整个树结构上面的每一笔交易记录的Hash值需要重算。</p><p>最终导致MerkleRoot这个数字会发生变化，一旦有变化，就会导致块头的Hash值发生变化。导致这个账单录入之后的所有账单的PrevBlockHash值发生改变，这个块之后的所有的帐要全部作废重做。区块链就是通过这样一个管理模式来管理账单。</p><p>其实到此为止区块链已经讲完了。区块链其实就是一个简单的记账模型，目的是为了避免有人为意图的对账单做修改。区块链的每一个块都是在随着交易记录的增加不停地添加进来的。因为任何一个块的数据都被一个完善的数学系统锁定了，任何一个字都是不可修改的，只要有修改，都需要重算从这个账单块开始的后面所有的账单块，否则账单就是一个错误账单，不会被系统采纳了。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[Spring Boot入门实践02--整和mybatis]]></title>
            <link>https://paragraph.com/@xiaoming/spring-boot-02-mybatis</link>
            <guid>oa3sMHYkx3MvZDp36AkL</guid>
            <pubDate>Sun, 09 Jan 2022 11:58:56 GMT</pubDate>
            <description><![CDATA[1.先贴出整个项目目录 项目目录 1.pom中加入mybatis的依赖org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 mysql mysql-connector-java 5.1.62.按项目目录添加文件 application.propertiesserver.port=8080 logging.level.org.springframework=DEBUG #springboot mybatis #jiazai mybatis peizhiwenjian mybatis.mapper-locations = classpath:mapper/*.xml mybatis.config-location = classpath:mapper/config/sqlMapConfig.xml mybatis.type-aliases-package = com.hhf.springboot.demo01.bean #shujuyuan spring.datasource.driver-class-name= com....]]></description>
            <content:encoded><![CDATA[<p>1.先贴出整个项目目录</p><p>项目目录</p><p>1.pom中加入mybatis的依赖</p><blockquote><p>org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 mysql mysql-connector-java 5.1.6</p></blockquote><p>2.按项目目录添加文件</p><p>application.properties</p><blockquote><p>server.port=8080</p><p>logging.level.org.springframework=DEBUG</p><p>#springboot mybatis</p><p>#jiazai mybatis peizhiwenjian</p><p>mybatis.mapper-locations = classpath:mapper/*.xml</p><p>mybatis.config-location = classpath:mapper/config/sqlMapConfig.xml</p><p>mybatis.type-aliases-package = com.hhf.springboot.demo01.bean</p><p>#shujuyuan</p><p>spring.datasource.driver-class-name= com.mysql.jdbc.Driver</p><p>spring.datasource.url = jdbc:mysql://localhost:3306/youxiake?useUnicode=true&amp;characterEncoding=utf-8</p><p>spring.datasource.username = root</p><p>spring.datasource.password = 123456</p></blockquote><p>tip:注意端口包名</p><p>User.class</p><blockquote><p>public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private Integer id; private String username; private Date birthday; private String sex; private String address; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }</p></blockquote><p>UserMapper.class</p><blockquote><p>@Mapper public interface UserMapper { public List findAll(); }</p><p>UserService.class</p><blockquote><p>public interface UserService { /** * 根据接口查询所用的用户 */ public List findAllUser(); }</p><p>UserServiceImpl.class</p><blockquote><p>@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; public List findAllUser() { List list = userMapper.findAll(); return list; } } UserMapper.xml select * from user</p></blockquote></blockquote></blockquote>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[2021安卓开发工作总结]]></title>
            <link>https://paragraph.com/@xiaoming/2021</link>
            <guid>UtDIRdlouE1Dn9ZxWoRo</guid>
            <pubDate>Sun, 09 Jan 2022 11:58:25 GMT</pubDate>
            <description><![CDATA[今年工作内容 1.社区和目的地改版，增加目的地板块。 2.遇见改版，遇见增加目的地，连通目的地板块。 3.增加会员板块和地图 4.遇见详情推荐更多。 5.遇见页面整体瀑布流化，页面组件化。 6.遇见录音板块。 7.遇见搜索板块板块改版，增加红人榜 8态度类话题改版，增加遇见功能。 一、通过日常工作积累使我对社交和旅游有了新的认识和一定了解。 二、Android开发技能的提升。今年随着业务的需求，对UI和页面有了新的要求。对自定义控件和封装有了新的提升。另外逐渐减少布局页面的层级，统一好封装功能组件。加快了开发的进度。对性能的要求，减少api请求，优化App冷启动时间。学习和理解插件化知识能将应用到项目，结合公司项目系统学习组件化架构的设计与理念。 三、对前端的了解。利用业余时间，学了网页端开发语言，HTML、CSS、JavaScript和小程序开发，继续扩展了技术领域。 四、坚持浏览博客，学习新的框架和了解前沿的开发知识。 总结： 业精于勤而荒于嬉”，在以后的工作中我要不断学习业务知识，通过多看、多问、多学、多练来不断的提高自己的各项业务技能。学无止境，时代的发展瞬息万变，各种学...]]></description>
            <content:encoded><![CDATA[<p>今年工作内容</p><p>1.社区和目的地改版，增加目的地板块。</p><p>2.遇见改版，遇见增加目的地，连通目的地板块。</p><p>3.增加会员板块和地图</p><p>4.遇见详情推荐更多。</p><p>5.遇见页面整体瀑布流化，页面组件化。</p><p>6.遇见录音板块。</p><p>7.遇见搜索板块板块改版，增加红人榜</p><p>8态度类话题改版，增加遇见功能。</p><p>一、通过日常工作积累使我对社交和旅游有了新的认识和一定了解。</p><p>二、Android开发技能的提升。今年随着业务的需求，对UI和页面有了新的要求。对自定义控件和封装有了新的提升。另外逐渐减少布局页面的层级，统一好封装功能组件。加快了开发的进度。对性能的要求，减少api请求，优化App冷启动时间。学习和理解插件化知识能将应用到项目，结合公司项目系统学习组件化架构的设计与理念。</p><p>三、对前端的了解。利用业余时间，学了网页端开发语言，HTML、CSS、JavaScript和小程序开发，继续扩展了技术领域。</p><p>四、坚持浏览博客，学习新的框架和了解前沿的开发知识。</p><p>总结：</p><p>业精于勤而荒于嬉”，在以后的工作中我要不断学习业务知识，通过多看、多问、多学、多练来不断的提高自己的各项业务技能。学无止境，时代的发展瞬息万变，各种学科知识日新月异。我将坚持不懈地努力学习各种知识，并用于指导实践。在今后工作中，要努力做好开发人员的本职工作，把自己的工作创造性做好做扎实，为项目的开发以及公司的发展贡献自己的力量。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[做副业有哪些网站，一旦知道，你就离不开了？]]></title>
            <link>https://paragraph.com/@xiaoming/hPRd2fZ3PVILURTgc539</link>
            <guid>hPRd2fZ3PVILURTgc539</guid>
            <pubDate>Sun, 09 Jan 2022 11:57:54 GMT</pubDate>
            <description><![CDATA[今天分享几个做副业常用的几个网站，我希望大家真的去登录下载，然后去了解，而不要看看几篇文章，这些网站非常的重要。离职的半年内，不断地尝试，不断的去积累，中间的艰辛也只有自己知道。下面罗列一些自己常用的一些网站分享给大家。 1，吾爱破解论坛（互联网的付费课程资源免费获取） 2，滚石技术导航（导航到其他第三方擦边网站） 3，猎手导航（导航到其他第三方网站） 4，盘多多（查找百度网盘各种云盘的资源） 5，葫芦侠3楼（查找各种擦边违规的第三方，未上架到应用商店的软件） 5，创客贴（制作微信公众号封面大图，各种海报或者是淘宝主页图） 6，cg资源网（编辑各种视频影视剪辑所利用到的视频素材） 7，爱给网（，制作抖音快手和各种视频所利用到的音效） 8，百度风云榜（自媒体文章发稿关键词搜索） 9，新榜（付费合作，同行优秀博主关注合作数据分析） 10，西瓜数据（微信公众号优秀同行关注列表） 11，新媒体管家（文章编辑整理与排版） 12，简媒（管理百家号，一点号，搜狐号，大鱼号，企鹅号，网易号） 13，5118大数据（通过互联网关键词大数据进行查找搜索） 14，小刀娱乐网（想刷抖音快手的播放量，可以...]]></description>
            <content:encoded><![CDATA[<p>今天分享几个做副业常用的几个网站，我希望大家真的去登录下载，然后去了解，而不要看看几篇文章，这些网站非常的重要。离职的半年内，不断地尝试，不断的去积累，中间的艰辛也只有自己知道。下面罗列一些自己常用的一些网站分享给大家。</p><p>1，吾爱破解论坛（互联网的付费课程资源免费获取）</p><p>2，滚石技术导航（导航到其他第三方擦边网站）</p><p>3，猎手导航（导航到其他第三方网站）</p><p>4，盘多多（查找百度网盘各种云盘的资源）</p><p>5，葫芦侠3楼（查找各种擦边违规的第三方，未上架到应用商店的软件）</p><p>5，创客贴（制作微信公众号封面大图，各种海报或者是淘宝主页图）</p><p>6，cg资源网（编辑各种视频影视剪辑所利用到的视频素材）</p><p>7，爱给网（，制作抖音快手和各种视频所利用到的音效）</p><p>8，百度风云榜（自媒体文章发稿关键词搜索）</p><p>9，新榜（付费合作，同行优秀博主关注合作数据分析）</p><p>10，西瓜数据（微信公众号优秀同行关注列表）</p><p>11，新媒体管家（文章编辑整理与排版）</p><p>12，简媒（管理百家号，一点号，搜狐号，大鱼号，企鹅号，网易号）</p><p>13，5118大数据（通过互联网关键词大数据进行查找搜索）</p><p>14，小刀娱乐网（想刷抖音快手的播放量，可以在这个论坛里面找到）</p><p>15，狸猫转换（爱奇艺的qIv格式可以用这个软件）</p><p>16，硕鼠下载（可以批量下载b站的视频）</p><p>17，格式工厂（音频，视频二者转换）</p><p>18，资源大亨网，福缘网，中赚网，大牛破解论坛</p><p>19，万兴神剪手（现在改名叫喵影工厂）</p><p>20，在线工具生成转化类（参考兔二工具）</p><p>21，图怪兽(在线图片编辑器)</p><p>22，PPT 超级市场（免费的 PPT 模板下载网站）</p><p>23,秘塔写作猫( AI 智能写作工具)</p><p>24，GitMind（免费的在线思维导图制作网站）</p><p>25，方案通-大量免费策划方案</p><p>26，超级简历-AI为你做简历</p><p>27，果汁排行榜</p><p>28，今日热榜</p><p>29，tunefind ——快速找到影视剧中的BGM</p><p>工作四年了，刚好赚了房子的首付和一辆代步车，手里有点积蓄就离职了。离职到现在半年了，从稳定的技术开发，到现在自己成立工作室，主要接一些企业的app和网站开发，另一方面自己尝试在自媒体方面发展。不断的了解和理解互联网的发展道路。觉得未来的发展机会在三四线城市，另外一方面好的内容创造者也会吃到这波的福利。投资方面，因为在投资股票之前，先了解了数字货币，会在比特币比较低的价格入一些。股票方面会投一下指数基金和一些比较厉害主动型基金。之后会定期更新一下近况和自己副业之路的各种想法。</p><p>目前手里有两个企业的app单子和一个律师的小程序开发。另外运营了三款自己的小程序。每个月的收入估计和之前在公司做开发持平。遇到的主要问题是时间不规律，与人沟通变少了。好的方面，时间会比较自由。写的乱七八糟的，希望未来一切变好。</p><p>喜欢我的可以关注我。微信公众号：技术副业</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[Int8，Int16，Int32，Int64 有啥不同呢？]]></title>
            <link>https://paragraph.com/@xiaoming/int8-int16-int32-int64</link>
            <guid>3wIjOtMuYnp5Gedujg9j</guid>
            <pubDate>Sun, 09 Jan 2022 11:57:21 GMT</pubDate>
            <description><![CDATA[Int8，Int16, Int32, Int64有什么区别呢？或者是为什么后面的数字不一样呢？ 初步了解了一下，才清楚这个东西。 先来扫盲一下计算机存储单元， 在计算机内部，信息都是釆用二进制的形式进行存储、运算、处理和传输的。信息存储单位有位、字节和字等几种。各种存储设备存储容量单位有KB、MB、GB和TB等几种 计算机的基本的存储单元有： 位（bit）：二进制数中的一个数位，可以是0或者1，是计算机中数据的最小单位。二进制的一个“0”或一个“1”叫一位。 字节（Byte，B）：计算机中数据的基本单位，每8位组成一个字节。各种信息在计算机中存储、处理至少需要一个字节。 ASCIIS码： 1个英文字母（不分大小写）= 1个字节的空间 1个中文汉字 = 2个字节的空间 1个ASCII码 = 一个字节 UTF-8编码：1个英文字符 = 1个字节 英文标点 = 1个字节 1个中文（含繁体） = 3个字节 中文标点 = 3个字节 Unicode编码：1个英文字符 = 2个字节 英文标点 = 2个字节 1个中文（含繁体） = 2个字节 中文标点 = 2个字节 字（Word）：两个字节称为一...]]></description>
            <content:encoded><![CDATA[<p>Int8，Int16, Int32, Int64有什么区别呢？或者是为什么后面的数字不一样呢？</p><p>初步了解了一下，才清楚这个东西。</p><p>先来扫盲一下计算机存储单元，</p><p>在计算机内部，信息都是釆用二进制的形式进行存储、运算、处理和传输的。信息存储单位有位、字节和字等几种。各种存储设备存储容量单位有KB、MB、GB和TB等几种</p><p>计算机的基本的存储单元有：</p><p>位（bit）：二进制数中的一个数位，可以是0或者1，是计算机中数据的最小单位。二进制的一个“0”或一个“1”叫一位。</p><p>字节（Byte，B）：计算机中数据的基本单位，每8位组成一个字节。各种信息在计算机中存储、处理至少需要一个字节。</p><p>ASCIIS码： 1个英文字母（不分大小写）= 1个字节的空间</p><p>1个中文汉字 = 2个字节的空间</p><pre data-type="codeBlock" text="                1个ASCII码 = 一个字节
"><code><span class="hljs-code">                1个ASCII码 = 一个字节
</span></code></pre><p>UTF-8编码：1个英文字符 = 1个字节</p><pre data-type="codeBlock" text="                 英文标点  = 1个字节

                 1个中文（含繁体） = 3个字节
"><code><span class="hljs-code">                 英文标点  = 1个字节
</span>
<span class="hljs-code">                 1个中文（含繁体） = 3个字节
</span></code></pre><p>中文标点 = 3个字节</p><p>Unicode编码：1个英文字符 = 2个字节</p><pre data-type="codeBlock" text="                 　英文标点  = 2个字节

                 　1个中文（含繁体） = 2个字节

                 　中文标点 = 2个字节                    　　　　　　    

   字（Word）：两个字节称为一个字。汉字的存储单位都是一个字。
"><code><span class="hljs-code">                 　英文标点  = 2个字节
</span>
<span class="hljs-code">                 　1个中文（含繁体） = 2个字节
</span>
<span class="hljs-code">                 　中文标点 = 2个字节                    　　　　　　    
</span>
   字（Word）：两个字节称为一个字。汉字的存储单位都是一个字。
</code></pre><p>扩展的存储单位有： 　 计算机存储容量大小以字节数来度量，1024进位制：</p><p>1024B=1K(千)B 　　 1024KB=1M(兆)B 　　 1024MB=1G(吉)B 　　 1024GB=1T(太)B</p><p>这是常用的五个，至于PB，EB，ZB，YB，BB，NB，DB几乎在日常使用中是不会遇到的。</p><p>而Int8，Int16，Int32，nt64，后面的数字就代表这个数据类型占据的空间。</p><pre data-type="codeBlock" text="   Int8, 等于Byte, 占1个字节.
"><code>   Int8, 等于<span class="hljs-built_in">Byte</span>, 占<span class="hljs-number">1</span>个字节.
</code></pre><p>Int16, 等于short, 占2个字节. -32768 32767</p><p>Int32, 等于int, 占4个字节. -2147483648 2147483647</p><p>Int64, 等于long, 占8个字节. -9223372036854775808 9223372036854775807</p><p>这样, 看起来比short,int,long更加直观些!</p><p>另外, 还有一个Byte, 它等于byte, 0 - 255.</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[理科生想学计算机方面，有什么专业推荐？]]></title>
            <link>https://paragraph.com/@xiaoming/916mFN2iFOSFc9g7cgtq</link>
            <guid>916mFN2iFOSFc9g7cgtq</guid>
            <pubDate>Sat, 27 Nov 2021 12:37:08 GMT</pubDate>
            <description><![CDATA[计算机方面 专业计算机科学与技术 软件工程 物联网 通信工程。其他专业也可以学习一些基本的计算机知识，有利于在以后的工作中增加技能点。前面提到的计算机专业 其实本科阶段上的课程基本都差不多，主要是掌握计算机的一些基础知识。后面还是看自己选择的择业方向。]]></description>
            <content:encoded><![CDATA[<p>计算机方面 专业计算机科学与技术 软件工程 物联网 通信工程。其他专业也可以学习一些基本的计算机知识，有利于在以后的工作中增加技能点。前面提到的计算机专业 其实本科阶段上的课程基本都差不多，主要是掌握计算机的一些基础知识。后面还是看自己选择的择业方向。</p>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
        <item>
            <title><![CDATA[如何看待防沉迷新规后的首个长假，家长表示「孩子玩网游少了，看游戏直播多了」？]]></title>
            <link>https://paragraph.com/@xiaoming/x9gUzFRmAYkK4pWBsLjX</link>
            <guid>x9gUzFRmAYkK4pWBsLjX</guid>
            <pubDate>Sun, 10 Oct 2021 09:34:59 GMT</pubDate>
            <description><![CDATA[如何看待防沉迷新规后的首个长假，家长表示「孩子玩网游少了，看游戏直播多了」？]]></description>
            <content:encoded><![CDATA[<h1 id="h-" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">如何看待防沉迷新规后的首个长假，家长表示「孩子玩网游少了，看游戏直播多了」？</h1>]]></content:encoded>
            <author>xiaoming@newsletter.paragraph.com (xiaoming.eth)</author>
        </item>
    </channel>
</rss>