2018年5月

1.联合概率分布
联合概率分布简称联合分布,是两个及以上随机变量组成的随机向量的概率分布。根据随机变量的不同,可分为离散型联合概率分布和连续型联合概率分布

①离散型联合概率分布:
设X和Y都是离散型随机变量,变量X和Y的联合分布完全决定X的概率分布和Y的概率分布:
请输入图片描述

请输入图片描述

X和Y的联合概率分布可以表示为:
请输入图片描述

例:
假设X和Y都是离散型分布

X的概率分布如下:
P(X=0)=0.4
P(X=1)=0.6

Y的概率分布如下:
P(Y=0)=0.25
P(Y=1)=0.5
P(Y=2)=0.25  

又因为X与Y相互独立,所以(X,Y)的联合概率分布为:
P(X=0,Y=0)=0.1
P(X=0,Y=1)=0.2
P(X=0,Y=2)=0.1
P(X=1,Y=0)=0.15
P(X=1,Y=1)=0.3
P(X=1,Y=2)=0.15

②连续型联合概率分布:
设X和Y为连续型随机变量,以 f1(x)和f2(y) 分别表示X和Y的概率密度:
请输入图片描述

请输入图片描述

X和Y的联合概率分布可以表示为:
请输入图片描述

2.条件概率分布
当对于一组随机变量,考虑其中某些变量取值特定值时,其余变量的分布是一种条件分布。

P(X=xi|Y=yi)=P(X=xi,Y=yi)/P(Y=yi)
为在Y=yi条件下X的条件分布率. (其中i为固定的),也称作该联合分布在Y上的条件分布。
请输入图片描述

3.边缘概率分布
一旦定义了随机变量,我们就可以在能够用X描述的事件上考虑分布。这个分布通常称为随机变量X的边缘分布 ,记为P(X). 这时单独只考虑X的取值,与其它随机变量取什么值的概率无关。

例:请输入图片描述变量I的边缘分布概率为:

P(I=0)=0.126+0.168+0.126+0.009+0.045+0.126
P(I=1)=0.252+0.0224+0.0056+0.06+0.036+0.024

前言

接口文档规范了接口信息的书写格式,把接口文档写规范了,前后端对接的时候就能省事很多。
一个项目是有n个接口的,为了方便管理这n个接口文档,我们使用的是VS Code。
本文主要针对后台管理的操作,查看操作请参照接口说明文档(前端版),如有缺漏请留言,谢谢。

接口文档的规范

例子如下:
此处输入图片的描述

主要分为以下三个部分:

1.请求参数说明(上面的绿字)

请求方式: (GET/POST)

 参数     是否必填         参数格式        参数作用

  a    (必填/非必填)  (String/int)      xxxxx

  b    (必填/非必填)  (String/int)      xxxxx

  c    (必填/非必填)  (String/int)      xxxxx

2.请求接口成功的示例(中间的白字)

GET/POST请求   GET/POST {{ipaddr}}/XXXXXXX

               ?json={"a":"xxxxxx","b":"xxxxxx","c":"xxxxxx"}


    
    ipaddr是配置的运行环境,具体详情在下方的定义全局变量有说。
    a、b、c均为参数,xxxxxx为该参数的值。
     

3.返回参数说明(下面的绿字)

返回参数          描述

    A        返回参数A的描述

    B        返回参数B的描述

VSCode使用

一、使用VS Code增加、删除、修改文件到码云

  1. 增加、删除、修改文件。
  2. 打开‘源代码管理’,点击‘+’,把更改提交到暂存区
    (当鼠标移至更改当中,会出现'+'按钮)

此处输入图片的描述

3.点击‘’提交暂存区的文件,填写提交信息后按Enter。

(此时暂存区的修改都被提交,列表为空)

再点击界面下方的图标进行上传 (平时更新下拉也可以点击这个图标)

此处输入图片的描述

4.更新完成


二、定义全局变量

示例当中的{{ipaddr}}为封装好的全局变量,ipaddr只是我们自己给的一个名字,没有什么特殊含义。
打开.vscode/settings.json,文件配置全局变量代码如下:


{
    "rest-client.environmentVariables": {
        "$shared": {
            "version": "v1"
        },
        "local": {
            "ipaddr": "http://127.0.0.1/parchment",
            "token": "test token"
        },
        "net": {
            "ipaddr": " ",
            "token": "test token"
        }
    }
}

在local环境中,我们给ipaddr的赋值为http://127.0.0.1/parchment,net同理。
使用全局变量的好处是当我们请求的时候,简化了更换地址的操作。如果出现了项目需要换测试环境的情况,也不需要一个一个地去更改接口文档。

前言

前端每实现一个接口,需要清楚知道要传的参数和返回的信息。
接口文档规范了接口信息的书写格式,前端人员只需要看懂了下面的规范便能轻松地了解所有接口的信息。
一个项目是有n个接口的,为了方便管理、查看这n个接口文档,我们使用的是VS Code。

接口文档的规范

为了方便大家快速看懂,我们用一个简单例子来解释。(查看用户预约成功后的信息)
此处输入图片的描述

主要分为以下三个部分:

1.请求参数说明(上面的绿字)

请求方式: (GET/POST)

 参数     是否必填         参数格式        参数作用

  a    (必填/非必填)  (String/int)      xxxxx

  b    (必填/非必填)  (String/int)      xxxxx

  c    (必填/非必填)  (String/int)      xxxxx

2.请求接口成功的示例(中间的白字)

GET/POST请求   GET/POST {{ipaddr}}/XXXXXXX

               ?json={"a":"xxxxxx","b":"xxxxxx","c":"xxxxxx"}


    Send Request是一个点击按钮,用于发送请求,具体解释在后面的VSCode使用当中。
    ipaddr是配置的请求地址。如有兴趣了解,可以看接口文档使用说明(后端版)。
    a、b、c均为参数,xxxxxx为该参数的值。
     

3.返回参数说明(下面的绿字)

返回参数          描述

    A        返回参数A的描述

    B        返回参数B的描述

VSCode使用

一、软件准备

  1. VS Code
  2. Git for windows (ios不用下载)

二、使用GitBash(Git for windows)从码云下拉接口文档

  1. 打开Git Bash
  2. 按顺序输入以下命令

    • 选择保存路径
      cd {ProjectPath}

    (例 cd F:,即为保存在F盘)

    • 克隆项目
      git clone {GitURL}

    (每个项目的URL不一样,根据实际情况输入。例:git clone https://gitee.com/D_e_n_g/parchment-api_images.git)

    第一次使用GitBash会出现提示框要求输入码云帐号密码,输入正确后获得对应的下拉权限。

  3. 下拉文档完成

三、使用VS Code查看接口文档、测试接口

  1. 从导航栏的文件中选择打开文件夹,注意!是文件夹!
  2. 打开扩展,安装REST Client并启动 。

该组件的作用是使接口文档的示例上方出现send Request,并对示例链接进行请求。

3.打开任意接口文档,选择环境变量

在软件的右下方点击No Environment,上方弹框选择net。每次点击SendRequest是在测试环境进行接口请求。local是后端人员进行开发时所用。

No Environment没有显示的问题:
1.只有后缀名为.http的文件才会有这一选项
2.REST Client组件没有启动,进入扩展选择启动

4.打开接口文档,发送请求
点击链接上的Send Request,右方会出现请求返回结果。
此处输入图片的描述

四、VSCode同步代码

  1. 打开‘源代码管理’ ,左侧导航栏的第三个
  2. 单击右上角的‘···’→点击‘同步
  3. 同步代码完成

前言

Android开发必不可少的就是和Toolbar打交道,毕竟它可以在标题栏自定义很多东西。之前做项目的时候一直想怎么把toolbar封装起来。最开始的做法是写一个含有toolbar的布局,然后在activity的布局里面include进去。但是这样每次写一个页面的时候都要实例一次这玩意。(虽然它是可以自定义内容,但是项目的页面toolbar一般都是大同小异的,只有少部分页面出现多一个按钮,少一个图标的情况。而每次写activity的时候都要重复写那几行代码实在不科学!)后来在网上看到了一种方法:将toolbar封在BaseActivity中,以后写代码就一劳永逸了。


编写一个toolbar的布局

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <android.support.v7.widget.Toolbar
    android:layout_height="?attr/actionBarSize"
    android:layout_width="match_parent"
    android:id="@+id/id_tool_bar"
    android:background="@color/action_bar_color"
    app:titleTextColor="@color/doument_white"
    app:subtitleTextColor="@color/doument_white"
    app:titleMarginStart="15dp"
    android:elevation="15dp"
    >
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="gone"
        android:textColor="@color/doument_white"
        android:textSize="18dp"/>
</android.support.v7.widget.Toolbar>
</FrameLayout>

这里的东西都可以自定义的,比如我自定义了两个标题的文本颜色、背景色、还有一个自定义View(用作有需要标题居中需求时使用)。如果你不想使用它自带的menu功能也可以在里面加个按钮什么的,反正toolbar是一个ViewGroup只要考虑布局就好。


一个toolbar的帮助类

public class ToolBarHelper {

/*上下文,创建view的时候须要用到*/
private Context mContext;

/*base view*/
private FrameLayout mContentView;

/*用户定义的view*/
private View mUserView;

/*toolbar*/
private Toolbar mToolBar;

/*视图构造器*/
private LayoutInflater mInflater;

/*自定义title*/
private TextView mTitle;
/*
 * 两个属性
 * 1、toolbar是否悬浮在窗体之上
 * 2、toolbar的高度获取
 * */
private static int[] ATTRS = {
        R.attr.windowActionBarOverlay,
        R.attr.actionBarSize
};

public ToolBarHelper(Context context, int layoutId) {
    this.mContext = context;
    mInflater = LayoutInflater.from(mContext);
    /*初始化整个内容*/
    initContentView();
    /*初始化用户定义的布局*/
    initUserView(layoutId);
    /*初始化toolbar*/
    initToolBar();
}

private void initContentView() {
    /*直接创建一个帧布局,作为视图容器的父容器*/
    mContentView = new FrameLayout(mContext);
    ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT);
    mContentView.setLayoutParams(params);

}

private void initToolBar() {
    /*通过inflater获取toolbar的布局文件*/
    View toolbar = mInflater.inflate(R.layout.toolbar_common, mContentView);
    mToolBar = (Toolbar) toolbar.findViewById(R.id.id_tool_bar);
    mTitle=(TextView) toolbar.findViewById(R.id.title);
}

private void initUserView(int id) {
    mUserView = mInflater.inflate(id, null);
    FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    TypedArray typedArray = mContext.getTheme().obtainStyledAttributes(ATTRS);
    /*获取主题中定义的悬浮标志*/
    boolean overly = typedArray.getBoolean(0, false);
    /*获取主题中定义的toolbar的高度*/
    @SuppressLint("ResourceType") int toolBarSize = (int) typedArray.getDimension(1,(int) mContext.getResources().getDimension(R.dimen.abc_action_bar_default_height_material));
    typedArray.recycle();
    /*假设是悬浮状态,则不须要设置间距*/
    params.topMargin = overly ? 0 : toolBarSize;
    mContentView.addView(mUserView, params);

}

public FrameLayout getContentView() {
    return mContentView;
}

public Toolbar getToolBar() {
    return mToolBar;
}

            /*********************外部方法******************************/
public ToolBarHelper setTitle(String title){
    mToolBar.setTitle(title);
    return this;
}

public ToolBarHelper setTitle(int resId){
    mToolBar.setTitle(resId);
    return this;
}

public ToolBarHelper setSubtitle(String subTitle){
    mToolBar.setSubtitle(subTitle);
    return this;
}

public ToolBarHelper setSubtitle(int resId){
    mToolBar.setSubtitle(resId);
    return this;
}

public ToolBarHelper setNavigationIcon(Drawable drawable) {
    mToolBar.setNavigationIcon(drawable);
    return this;
}

public ToolBarHelper setNavigationIcon(int resId) {
    mToolBar.setNavigationIcon(resId);
    return this;
}

public ToolBarHelper setLogo(int resId){
    mToolBar.setLogo(resId);
    return this;
}

public ToolBarHelper setCustomTitle(String title){
    mTitle.setVisibility(View.VISIBLE);
    mTitle.setText(title);
    return this;
}

public ToolBarHelper setCustomTitle(int resId){
    mTitle.setVisibility(View.VISIBLE);
    mTitle.setText(mContext.getText(resId));
    return this;
}
}

这个帮助类通过外部activity传入的布局调节这整个布局的上边距 margin_top,来适配加入toolbar之后的页面样式。然后通过上面写的toolbar的布局实例化toolbar也包括里面包含的自定义view(这里可以按实际情况进行修改)。同时我也自定义了一些外部方法,调用这些方法来设置title、icon之类的属性。可以按实际需要进行添加。


在BaseActivity中操作该帮助类

首先定义toolbar和toolbarHelper的对象

public ToolBarHelper mToolBarHelper ;
private Toolbar toolbar ;

ToolBarHelper定义的是public的,方便子类通过它来调用上述写的一些外部方法。

然后是重写activity的setContentView方法

    @Override
public void setContentView(int layoutResID) {
    mToolBarHelper = new ToolBarHelper(this,layoutResID) ;
    toolbar = mToolBarHelper.getToolBar() ;
    setContentView(mToolBarHelper.getContentView());
    /*把 toolbar 设置到Activity 中*/
    setSupportActionBar(toolbar);
    /*自己定义的一些操作*/
    onCreateCustomToolBar(toolbar) ;
}

将activity布局的id传给toolBarHelper,生成对应的布局和toolbar后再重新设置到activity中显示。然后onCreateCustomToolBar(toolbar) 这个方法是用作写一些toolbar的相关设置的。比如可以写一些以前关于toolbar重复较高的代码

    public void onCreateCustomToolBar(Toolbar toolbar){
     toolbar.setContentInsetsRelative(0,0);
     getSupportActionBar().setDisplayShowTitleEnabled(false);                    //设置隐藏应用名
     toolbar.setNavigationOnClickListener(new View.OnClickListener() {           //默认点击事件
        @Override
        public void onClick(View v) {
            finish();
        }
    });
   }

注:上面的setNavigationOnClickListener如果有特殊需要的话在子类中将toolbar通过toolbarHelper的get方法拿出来然后重写监听就可以了。其他方法重写类似


最后

说实话,这个封装解决了我这么久对于toolbar的代码强迫症,个人感觉还是比较实用的。
最后贴一张山寨微信的图,比上次好看了一点。这个也是我用封装的toolbar写的!
screenshot-1525441150794.jpg

前言

看了google官方的MVP模式结构和一些不同网络上的文章,有比较多优化之前所说的普通mvp模式的方案。今天就说说google官方推荐的一个mvp形式。


Contract类

google在原先mvp三层结构分开不同类和不同结构的基础上加入了一个叫Contract的类,中文翻译是契约的意思。主要作用就是将三层(M、V、P)或者两层(V、P)的接口做一个管理。至于为什么会出现只有两层,后面会说...

public class WXContract {
 interface View extends BaseView {
    void setData(List<WXInfoModle> list);
}

 interface  Presenter extends BasePresenter<View> {
    void loadData();
}  }

这是上一次我写微信好友列表的V层还有P层的接口,采用契约后我把改成了上面这样的代码。两个接口都存在继承,这是关系到mvp模式的封装问题。这里我是直接使用android studio的插件生成的。这里有这个插件的教程,可以看看:请输入链接描述
使用插件生成的代码也包括了BaseActivity和BaseFragment的封装,base的P层直接封装在它们的里面。同理,base的V层直接封装在base的P层。所以在实际使用时不需要实例出来。


关于Model层的应用问题

网上对于M层的作用出现得比较多的有两个版本,一个是像我之前写的用它来初始化数据,比如生成一个list或者网络请求拿数据,但是我看了比较多的文章包括google的官方版本他们都比较倾向将M层用作bean类来使用,就是仅仅只是用它来做自定义类的封装。而把数据的初始化之类的操作交给了P层。也就出现了上述所说的契约类只管理两层的接口,因为这样的话M层压根没有接口。本人暂时分析不出孰优孰劣。但我本人也倾向于第二种方案,毕竟P层如果单单是调用M层和V层的方法感觉有点浪费,而且代码也有点强迫症了(个人感觉~~)。
所以最后P层的代码就取代了原来M层的代码。在P层完成list的生成后直接后调给V层

public class WXPresenter extends BasePresenterImpl<WXContract.View> implements WXContract.Presenter{
 private List<WXInfoModle> list;

 @Override
 public void loadData() {
    list=new ArrayList<>();
    for(int i=0;i<10;i++){
        WXInfoModle wxInfoBean=new WXInfoModle();
        wxInfoBean.setUserName(i+"");
        wxInfoBean.setInfoDetail("Hello WeChat!");
        wxInfoBean.setInfoTime(i+"");
        list.add(wxInfoBean);
    }
    mView.setData(list);
}
 }

最后

这个是google官方对于MVP模式demo的GitHub,里面包括这种最基本的还有其他不同魔改版的mvp模式:请输入链接描述
还有上面说到插件这里也说一个有关Android的控件实例化、事件监听的注解式生成工具插件:请输入链接描述 用这个可以大大提高开发效率,说实话个人感觉findViewById是一个很坑的方法(控件多起来简直要命!)。