Android仿钉钉物品采购输入保存JSON串

图片.png

公司要求做这么一个列表展示可以输入的EditText一个listView的列表,有点像钉钉的物品采购模块,并且价格需要自动计算,数量乘以单价,上图所示的类似效果图,点击添加按钮可以新增一组条目用于填写,删除按钮可以删除一组条目。下面直接展示主要逻辑部分代码。时间部分在demo里面忽略掉了。可以用自己喜欢的时间框架.

首先是Activity的布局文件:mListView 是一项目中常用的和ScroolView嵌套的ListView布局,也可以用 RecylerView 代替

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@color/white">

        <RelativeLayout
            android:id="@+id/rl_back"
            android:layout_width="48dp"
            android:layout_height="match_parent">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@drawable/icon_left_back"/>
        </RelativeLayout>

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="Title"
            android:textColor="#333333"
            android:textSize="16sp"/>

        <RelativeLayout
            android:id="@+id/rl_right"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_marginRight="15dp"
            >

            <TextView
                android:id="@+id/tv_right"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="right"
                android:textColor="#333333" />
        </RelativeLayout>
    </RelativeLayout>


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <com.lzy.demoedittextinput.mListView
            android:id="@+id/lv_goods_purchase"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:divider="@null"
            android:scrollbars="none"/>

    </ScrollView>

    <TextView
        android:id="@+id/tv_commit"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@color/white"
        android:gravity="center"
        android:text="+ 新增物品"
        android:textColor="#000"
        android:textSize="16sp"/>

</LinearLayout>

下面是Activity代码,记得在清单文件注册。

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.List;

public class GoodsPurchaseParticularsActivity extends AppCompatActivity implements View.OnClickListener {

    private List<GoodsPurchaseEntity> mList = new ArrayList<>();
    private CreateGoodsPurChaseAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_goods_purchase_particulars);
        String article_purchase = getIntent().getStringExtra("article_purchase");
        if (article_purchase != null) {
            mList = JSON.parseArray(article_purchase, GoodsPurchaseEntity.class);
        } else {

            mList.add(new GoodsPurchaseEntity());
        }

        mAdapter = new CreateGoodsPurChaseAdapter(this, mList);

        RelativeLayout rl_back = (RelativeLayout) findViewById(R.id.rl_back);
        TextView tv_title = (TextView) findViewById(R.id.tv_title);
        ListView lv_goods_purchase = (ListView) findViewById(R.id.lv_goods_purchase);
        TextView tv_commit = (TextView) findViewById(R.id.tv_commit);
        RelativeLayout rl_right = (RelativeLayout) findViewById(R.id.rl_right);
        TextView tv_right = (TextView) findViewById(R.id.tv_right);

        tv_title.setText("明细");
        tv_right.setText("确定");
        mList.add(new GoodsPurchaseEntity());

        rl_back.setOnClickListener(this);
        tv_commit.setOnClickListener(this);
        rl_right.setOnClickListener(this);
        lv_goods_purchase.setAdapter(mAdapter);

        mAdapter.setOnDeleteItemListener(new CreateGoodsPurChaseAdapter.onDeleteItemListener() {
            @Override
            public void deleteItemListener(int position) {
                mList.remove(position);
                mAdapter.notifyDataSetChanged();
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.rl_back:
                finish();
                break;

            case R.id.tv_commit:
                mList.add(new GoodsPurchaseEntity());
                mAdapter.notifyDataSetChanged();
                break;

            case R.id.rl_right:
                submit();
                break;
        }
    }

    private void submit() {
        for (int i = 0; i < mList.size(); i++) {
            String norms = mList.get(i).getNorms();
            String name = mList.get(i).getName();
            String num = mList.get(i).getNum();
            String units = mList.get(i).getUnits();
            String type = mList.get(i).getType();
            String unit_price = mList.get(i).getUnit_price();
            String all_price = mList.get(i).getAll_price();

            if (TextUtils.isEmpty(norms) || TextUtils.isEmpty(name) || TextUtils.isEmpty(num)
                    || TextUtils.isEmpty(units) || TextUtils.isEmpty(type)
                    || TextUtils.isEmpty(unit_price) || TextUtils.isEmpty(all_price)) {
                Toast.makeText(this, "明细填写不全", Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Double all_price = 0.00;
        String goods = JSON.toJSONString(mList);
        for (int i = 0; i < mList.size(); i++) {
            Double all_prices = Double.parseDouble(mList.get(i).getAll_price());
            all_price = all_price + all_prices;
        }

        Intent intent = new Intent();
        intent.putExtra("all_price", all_price + "");
        intent.putExtra("article_purchase", goods);
        intent.putExtra("num", mList.size() + "");
        setResult(RESULT_OK, intent);
        finish();
    }

    public void saveEditData(int position, String type, String str) {
        //数字用于区分EditText
        try {
            if ("1".equals(type)) {
                mList.get((position - 1) / 100).setType(str);
            } else if ("2".equals(type)) {
                mList.get((position - 2) / 100).setName(str);
            } else if ("3".equals(type)) {
                mList.get((position - 3) / 100).setNorms(str);
            } else if ("4".equals(type)) {
                mList.get((position - 4) / 100).setNum(str);
            } else if ("5".equals(type)) {
                mList.get((position - 5) / 100).setUnits(str);
            } else if ("6".equals(type)) {
                mList.get((position - 6) / 100).setUnit_price(str);
            } else if ("7".equals(type)) {
                mList.get((position - 7) / 100).setAll_price(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

下面是适配器代码,布局文件在后面。因为listView 先绘制的特性,所以思路是将EditText 的输入的值以监听的方式存入到实体中。

import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.text.DecimalFormat;
import java.util.List;


public class CreateGoodsPurChaseAdapter extends BaseAdapter {

    private Context mContext;
    private List<GoodsPurchaseEntity> mList;
    private onDeleteItemListener mOnDeleteItemListener;
    private final DecimalFormat mFormat;

    public CreateGoodsPurChaseAdapter(Context context, List<GoodsPurchaseEntity> list) {
        mContext = context;
        mList = list;
        mFormat = new DecimalFormat("##.##");
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_goods_purchase, null);

            holder = new ViewHolder(convertView, position);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (position == 0) {
            holder.tv_delete.setVisibility(View.GONE);
            // holder.tv_num.setText("采购明细");
        } else {
            holder.tv_delete.setVisibility(View.VISIBLE);
        }
        int i = position + 1;
        holder.tv_num.setText("采购明细(" + i + ")");

        holder.rl_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOnDeleteItemListener.deleteItemListener(position);
            }
        });
        holder.et_type.setTag(position * 100 + 1);
        holder.et_name.setTag(position * 100 + 2);
        holder.et_norms.setTag(position * 100 + 3);
        holder.et_num.setTag(position * 100 + 4);
        holder.et_units.setTag(position * 100 + 5);
        holder.et_unit_price.setTag(position * 100 + 6);
        holder.tv_all_price.setTag(position * 100 + 7);

        GoodsPurchaseEntity bean = mList.get(position);
        holder.et_type.setText(bean.getType());
        holder.et_name.setText(bean.getName());
        holder.et_norms.setText(bean.getNorms());
        holder.et_num.setText(bean.getNum());
        holder.et_units.setText(bean.getUnits());
        holder.et_unit_price.setText(bean.getUnit_price());
        holder.tv_all_price.setText(bean.getAll_price());


        return convertView;
    }

    class ViewHolder {
        private TextView tv_delete;
        private RelativeLayout rl_delete;
        private EditText et_type;
        private EditText et_name;
        private EditText et_norms;
        private EditText et_num;
        private EditText et_units;
        private EditText et_unit_price;
        private TextView tv_all_price;
        private TextView tv_num;

        public ViewHolder(View convertView, int position) {
            tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
            tv_num = (TextView) convertView.findViewById(R.id.tv_num);
            tv_all_price = (TextView) convertView.findViewById(R.id.tv_all_price);
            rl_delete = (RelativeLayout) convertView.findViewById(R.id.rl_delete);
            et_type = (EditText) convertView.findViewById(R.id.et_type);
            et_name = (EditText) convertView.findViewById(R.id.et_name);
            et_norms = (EditText) convertView.findViewById(R.id.et_norms);
            et_num = (EditText) convertView.findViewById(R.id.et_num);
            et_units = (EditText) convertView.findViewById(R.id.et_units);
            et_unit_price = (EditText) convertView.findViewById(R.id.et_unit_price);


            et_type.addTextChangedListener(new TextSwitcher(this, "1"));
            et_name.addTextChangedListener(new TextSwitcher(this, "2"));
            et_norms.addTextChangedListener(new TextSwitcher(this, "3"));
            et_num.addTextChangedListener(new TextSwitcher(this, "4"));
            et_units.addTextChangedListener(new TextSwitcher(this, "5"));
            et_unit_price.addTextChangedListener(new TextSwitcher(this, "6"));
            tv_all_price.addTextChangedListener(new TextSwitcher(this, "7"));
        }
    }

    class TextSwitcher implements TextWatcher {
        private ViewHolder mHolder;
        private String mType;

        public TextSwitcher(ViewHolder mHolder, String type) {
            this.mHolder = mHolder;
            mType = type;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            if ("1".equals(mType)) {
                int position = (Integer) mHolder.et_type.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("2".equals(mType)) {
                int position = (Integer) mHolder.et_name.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("3".equals(mType)) {
                int position = (Integer) mHolder.et_norms.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("4".equals(mType)) {
                int position = (Integer) mHolder.et_num.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());

                String et_num = mHolder.et_num.getText().toString();
                String units_price = mHolder.et_unit_price.getText().toString();
                if (TextUtils.isEmpty(et_num) || TextUtils.isEmpty(units_price)) {
                    mHolder.tv_all_price.setText("0");
                } else {
                    double all_price = Double.parseDouble(et_num) * Double.parseDouble(units_price);
                    String formatted = mFormat.format(all_price);
                    mHolder.tv_all_price.setText(formatted + "");
                }

            } else if ("5".equals(mType)) {
                int position = (Integer) mHolder.et_units.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());

            } else if ("6".equals(mType)) {
                int position = (Integer) mHolder.et_unit_price.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
                String et_num = mHolder.et_num.getText().toString();
                String units_price = mHolder.et_unit_price.getText().toString();
                if (TextUtils.isEmpty(et_num) || TextUtils.isEmpty(units_price)) {
                    mHolder.tv_all_price.setText("0");
                } else {
                    double all_price = Double.parseDouble(et_num) * Double.parseDouble(units_price);
                    String formatted = mFormat.format(all_price);
                    mHolder.tv_all_price.setText(formatted + "");
                }
            } else if ("7".equals(mType)) {
                if (mHolder.tv_all_price.getTag() != null) {
                    int position = (Integer) mHolder.tv_all_price.getTag();

                    ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
                }
            }
        }
    }

    public interface onDeleteItemListener {
        void deleteItemListener(int position);
    }

    public void setOnDeleteItemListener(onDeleteItemListener onDeleteItemListener) {
        mOnDeleteItemListener = onDeleteItemListener;
    }
}

下面是适配器Item布局,为了节省代码,封装了style

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_delete"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        >

        <TextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:text="报销明细"
            android:textSize="12sp"
            android:textColor="#999999"
            android:layout_height="match_parent"/>

        <TextView
            android:id="@+id/tv_delete"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:gravity="center_vertical"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="删除"
            android:textColor="#32a8fc"
            android:textSize="12sp"/>
    </RelativeLayout>


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

        <TextView
            android:text="采购类型"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_type"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

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

        <TextView
            android:text="物品名称"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_name"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

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

        <TextView
            android:text="规格        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_norms"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="数量        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_num"
            android:hint="请输入"
            android:inputType="number"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="单位        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_units"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="单价        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_unit_price"
            android:hint="请输入"
            android:inputType="numberDecimal"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="总价        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <TextView
            android:id="@+id/tv_all_price"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_weight="1"
            android:background="@null"
            android:gravity="center_vertical"
            android:hint="0"
            android:textColor="#333333"
            android:textColorHint="#999999"
            />

    </LinearLayout>

</LinearLayout>

style 如下

  <!-- 通用45dp #111 文字,提示文字#999 主要用于文字填写-->
    <style name="common_45dp_edittext">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:layout_marginLeft">10dp</item>
        <item name="android:background">@null</item>
        <item name="android:singleLine">true</item>
        <item name="android:textColor">#333333</item>
        <item name="android:textColorHint">#999999</item>
        <item name="android:textSize">14sp</item>
    </style>


    <!-- 通用45dp 白底 条目线性布局 主要用于条目选择-->
    <style name="common_45dp_linearLayout">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">45dp</item>

        <item name="android:gravity">center_vertical</item>
        <item name="android:orientation">horizontal</item>
    </style>

以上就是这个需求的主题逻辑和思路,如果有问题希望大家指正,也希望和有其他思路的大神交流学习。↖(▔.▔)↗

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • 前言 其实以前写过这么一片类似的文章链接,利用字符串+runtime能做到命名域级别的解耦,其实这种做法很极端,编...
    Link913阅读 901评论 2 2
  • 朋友问题:“源头是什么?是树状吗?是吸收養分嗎? 答:不是。 心脏,扑通扑通地跳动,产生了不少血液,流向了全身,不...
    古茜妲樹二阅读 636评论 0 3
  • 探索 ConcurrentHashMap 高并发性的实现机制
    Tony_HQ阅读 226评论 0 0