Android 基礎(chǔ)框架搭建

從業(yè)4年搭建的框架爽柒,歡迎吐槽浑此,提出意見修改

建議項(xiàng)目采用Retrofit2.0+RxJava2.0做網(wǎng)絡(luò)請求

BaseActivity

package com.listen.feng.base;

import android.app.Activity;
import android.content.ComponentName;
import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.listen.feng.R;
import com.listen.feng.common.LoadDialog;
import com.listen.feng.play.MusicService;
import com.listen.feng.util.UtilIntent;
import com.orhanobut.logger.Logger;

import io.reactivex.disposables.CompositeDisposable;

/**
 * Created by liu on 2017/9/25.
 */

public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
    protected BaseActivity mActivity;

    /**
     * 全局的加載框?qū)ο笙狗茫呀?jīng)完成初始化.
     */
    public LoadDialog mProgressDialog;
    private TextView mTvTitle;
    private ImageView mIvLeft;
    private TextView mTvRight;
    private ImageView mIvRight;
    protected FrameLayout actionBarLayout;
    protected FrameLayout errorLayout;
    protected FrameLayout contentLayout;
    private RelativeLayout rlRoot;
    private TextView tvTitle;
    private ImageButton ivBackBtn;
    private Button btnRefresh;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = this;
        getIntentData();
    }

    /**
     * 設(shè)置標(biāo)題
     * @return
     */
    protected abstract String setTitle();

    /**
     * 初始化View
     */
    protected abstract void initView();

    /**
     * 初始化數(shù)據(jù)
     */
    protected abstract void initData();

    /**
     * 獲取Intent參數(shù)
     */
    protected abstract void getIntentData();

    /**
     * 是否顯示標(biāo)題欄
     * @return
     */
    protected abstract boolean showActionBar();

    protected void reload(){

    };

    public CompositeDisposable mDisposable = new CompositeDisposable();


    @Override
    public void setContentView(@LayoutRes int layoutResID) {
        super.setContentView(R.layout.activity_base);
        contentLayout =  findViewById(R.id.frame_layout);
        actionBarLayout =  findViewById(R.id.actionbar);
        errorLayout =  findViewById(R.id.frame_error_layout);
        LayoutInflater.from(this).inflate(layoutResID, contentLayout);
        if(showActionBar()){
            actionBarLayout.setVisibility(View.VISIBLE);
            LayoutInflater.from(this).inflate(R.layout.base_actionbar, actionBarLayout);
            tvTitle =  actionBarLayout.findViewById(R.id.tv_title);
            ivBackBtn =  actionBarLayout.findViewById(R.id.iv_back_btn);
            ivBackBtn.setOnClickListener(this);
            if(!TextUtils.isEmpty(setTitle())) {
                tvTitle.setText(setTitle());
            }
        }else{
            actionBarLayout.setVisibility(View.GONE);
        }
        initView();
        initData();
    }


    public RelativeLayout getRlRoot() {
        return rlRoot;
    }

    /**
     * 設(shè)置中間標(biāo)題
     * @param str
     */
    protected void setCenterTitle(String str){
        tvTitle.setText(str);
    }

    /**
     * 顯示右面的圖標(biāo)
     * @param id
     */
    protected void showRightImage(int id){
        if(mTvRight != null){
            mTvRight.setVisibility(View.GONE);
        }
        if(mIvRight != null){
            mIvRight.setVisibility(View.VISIBLE);
            mIvRight.setImageResource(id);
            mIvRight.setOnClickListener(this);
        }
    }




    /**
     * 顯示右面的文字
     * @param str
     */
    protected void showRightText(String str){
        if(mIvRight != null){
            mIvRight.setVisibility(View.GONE);
        }
        if(mTvRight != null){
            mTvRight.setVisibility(View.VISIBLE);
            mTvRight.setText(str);
            mTvRight.setOnClickListener(this);
        }
    }

    protected void isShowRightImage(boolean b){

        if(mIvRight != null){
            mIvRight.setVisibility(b ? View.VISIBLE : View.GONE);
        }
    }

    protected void isShowRightTextView(boolean b){
        if(mTvRight != null){
            mTvRight.setVisibility(b ? View.VISIBLE : View.GONE);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.iv_back_btn:
                finishAnim(this);
                break;

            case R.id.btn_refresh:
                reload();
                break;
        }
    }

    /**
     * 顯示
     * @param resId
     */
    protected void setCustomActionBar(@LayoutRes int resId){
        actionBarLayout.setVisibility(View.VISIBLE);
        actionBarLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, actionBarLayout);
    }

    /**
     * 顯示有數(shù)據(jù)界面
     */
    protected void showDataLayout(){
        contentLayout.setVisibility(View.VISIBLE);
        errorLayout.setVisibility(View.GONE);
    }


    protected void showEmptyErrorLayout(){
        contentLayout.setVisibility(View.GONE);
        errorLayout.setVisibility(View.VISIBLE);
        errorLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(R.layout.error_empty_base_layout, errorLayout);
    }

    protected void showEmptyErrorLayout(@LayoutRes int resId){
        contentLayout.setVisibility(View.GONE);
        errorLayout.setVisibility(View.VISIBLE);
        errorLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, errorLayout);
    }

    protected void showErrorLayout(){
        contentLayout.setVisibility(View.GONE);
        errorLayout.setVisibility(View.VISIBLE);
        errorLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(R.layout.error_network_base_layout, errorLayout);
        btnRefresh = errorLayout.findViewById(R.id.btn_refresh);
        btnRefresh.setOnClickListener(this);
    }

    protected void showErrorLayout(@LayoutRes int resId){
        contentLayout.setVisibility(View.GONE);
        errorLayout.setVisibility(View.VISIBLE);
        errorLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, errorLayout);

    }


    protected void showErrorLayout(@LayoutRes int resId, View.OnClickListener listener, @IdRes int... id){
        contentLayout.setVisibility(View.GONE);
        errorLayout.setVisibility(View.VISIBLE);
        errorLayout.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, errorLayout);
        for (int i = 0; i < id.length; i++){
            findViewById(id[i]).setOnClickListener(listener);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mDisposable.dispose();
    }

    /**
     * 顯示加載框
     */
    public void showProgressDialog() {
        if (mProgressDialog == null) {
            mProgressDialog = new LoadDialog(this);
        }
        //如果加載框不顯示, 那么就顯示加載框
        if (!mProgressDialog.isShowing()) {
            mProgressDialog.show();
        }
    }

    /**
     * 移除加載框.
     */
    public void removeProgressDialog() {
        if (mProgressDialog != null) {
            if (mProgressDialog.isShowing()) {
                mProgressDialog.dismiss();
            }
        }
    }



    @Override
    public void onBackPressed() {
        finishAnim(this);
    }

    /**
     * 描述:Toast提示文本.
     *
     * @param text 文本
     */
    public void showToast(String text) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
    }

}

activity_base

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/rl_root"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <!-- 標(biāo)題欄 -->
    <FrameLayout
        android:id="@+id/actionbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ></FrameLayout>
    <!-- 錯誤 -->
    <FrameLayout
        android:id="@+id/frame_error_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/actionbar"
        android:visibility="gone">
    </FrameLayout>
    <!-- 正常內(nèi)容 -->
    <FrameLayout
        android:id="@+id/frame_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/actionbar">
    </FrameLayout>

</RelativeLayout>

BaseFragment

package com.listen.feng.base;

import android.os.Bundle;
import android.support.annotation.IdRes;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import com.listen.feng.R;

import io.reactivex.disposables.CompositeDisposable;

/**
 * Created by liu on 2017/9/26.
 */

public abstract class BaseFragment extends Fragment implements View.OnClickListener{
    private View baseView;
    protected FrameLayout frameContext;
    protected FrameLayout frameError;
    protected FrameLayout frameActionBar;
    protected BaseActivity mActivity;
    protected View rootView;
    protected CompositeDisposable mDisposable = new CompositeDisposable();
    /**
     * 全局的加載框?qū)ο螅呀?jīng)完成初始化.
     */
    protected abstract void initView();
    protected abstract void initData();
    protected abstract int getLayoutId();
    protected abstract boolean showActionBar();
    protected abstract void getIntentData();
    protected abstract int setActionBar();
    protected void reload(){

    };



    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity = (BaseActivity) getActivity();
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        if(baseView == null){
            baseView = inflater.inflate(R.layout.fragment_base, container,false);
            frameContext =  baseView.findViewById(R.id.frame_context);
            frameError =  baseView.findViewById(R.id.frame_error);
            frameActionBar =  baseView.findViewById(R.id.actionbar);
            rootView = inflater.inflate(getLayoutId(), frameContext);
            if(showActionBar()){
                frameActionBar.setVisibility(View.VISIBLE);
                inflater.inflate(setActionBar(), frameActionBar);
            }else{
                frameActionBar.setVisibility(View.GONE);
            }
            getIntentData();
            initView();
        }
        return baseView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initData();
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        mDisposable.dispose();
    }

    /**
     * 顯示自定義標(biāo)題欄
     * @param resId
     */
    protected void setCustomActionBar(@LayoutRes int resId){
        frameActionBar.setVisibility(View.VISIBLE);
        frameActionBar.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, frameActionBar);
    }

    protected void showDataLayout(){
        frameContext.setVisibility(View.VISIBLE);
        frameError.setVisibility(View.GONE);
    }

    protected void showEmptyErrorLayout(){
        frameContext.setVisibility(View.GONE);
        frameError.setVisibility(View.VISIBLE);
        frameError.removeAllViews();
        LayoutInflater.from(mActivity).inflate(R.layout.error_empty_base_layout, frameError);

    }

    protected void showErrorLayout(){
        frameContext.setVisibility(View.GONE);
        frameError.setVisibility(View.VISIBLE);
        frameError.removeAllViews();
        LayoutInflater.from(mActivity).inflate(R.layout.error_network_base_layout, frameError);
        frameError.findViewById(R.id.btn_refresh).setOnClickListener(this);
    }

    protected void showErrorLayout(@LayoutRes int resId){
        frameContext.setVisibility(View.GONE);
        frameError.setVisibility(View.VISIBLE);
        frameError.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, frameError);
    }


    protected void showErrorLayout(@LayoutRes int resId, View.OnClickListener listener, @IdRes int... id){
        frameContext.setVisibility(View.GONE);
        frameError.setVisibility(View.VISIBLE);
        frameError.removeAllViews();
        LayoutInflater.from(mActivity).inflate(resId, frameError);
        for (int i = 0; i < id.length; i++){
            frameError.findViewById(id[i]).setOnClickListener(listener);
        }
    }


    public void showToast(String text) {
        mActivity.showToast(text);
    }


    public void showProgressDialog(){
        mActivity.showProgressDialog();
    }

    public void removeProgressDialog(){
        mActivity.removeProgressDialog();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_refresh:
                reload();
                break;
        }
    }
}

fragment_base

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


    <FrameLayout
        android:id="@+id/actionbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></FrameLayout>

    <FrameLayout
        android:id="@+id/frame_error"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/actionbar"
        android:visibility="gone">
    </FrameLayout>

    <FrameLayout
        android:id="@+id/frame_context"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/actionbar">
    </FrameLayout>
</RelativeLayout>

BaseObserver

package com.listen.feng.base;

import android.text.TextUtils;

import com.listen.feng.bean.BaseResult;

import java.lang.ref.WeakReference;

import io.reactivex.observers.DisposableObserver;

/**
 * Created by liu on 2017/10/31.
 */

public class BaseObserver<T> extends DisposableObserver<BaseResult> {
    private WeakReference<BaseActivity> mActivityWeakReference;
    private WeakReference<BaseFragment> mFragmentWeakReference;
    //默認(rèn)顯示加載loading
    private boolean isShow = true;
    //是否顯示錯誤頁面
    private boolean isShowError = true;

    public BaseObserver(BaseActivity activity) {
        mActivityWeakReference = new WeakReference<BaseActivity>(activity);
    }

    public BaseObserver(BaseActivity activity, boolean b) {
        mActivityWeakReference = new WeakReference<BaseActivity>(activity);
        isShow = b;
    }

    public BaseObserver(BaseActivity activity, boolean b, boolean isShowError) {
        mActivityWeakReference = new WeakReference<BaseActivity>(activity);
        isShow = b;
        this.isShowError = isShowError;
    }

    public BaseObserver(BaseFragment fragment) {
        mFragmentWeakReference = new WeakReference<BaseFragment>(fragment);
    }

    public BaseObserver(BaseFragment fragment, boolean b) {
        mFragmentWeakReference = new WeakReference<BaseFragment>(fragment);
        isShow = b;
    }

    public BaseObserver(BaseFragment fragment, boolean b, boolean isShowError) {
        mFragmentWeakReference = new WeakReference<BaseFragment>(fragment);
        isShow = b;
        this.isShowError = isShowError;
    }


    @Override
    protected void onStart() {
        super.onStart();
        if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
            if (isShow) {
                mActivityWeakReference.get().showProgressDialog();
            }
        }
        if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
            if (isShow) {
                mFragmentWeakReference.get().showProgressDialog();
            }
        }
    }

    @Override
    public void onNext(BaseResult value) {
        if (value.getStatus() == 0) {
            if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
                mActivityWeakReference.get().showDataLayout();
            }
            if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
                mFragmentWeakReference.get().showDataLayout();
            }
            success(value);
        } else {
            if (!TextUtils.isEmpty(value.getMessage())) {
                if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
                    mActivityWeakReference.get().showToast(value.getMessage());
                }
                if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
                    mFragmentWeakReference.get().showToast(value.getMessage());
                }
            }
            error(value);
        }
    }

    public void success(BaseResult data) {
    }

    /**
     * 錯誤
     *
     * @param
     */
    public void error(BaseResult data) {
        if (isShowError) {
            if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
                mActivityWeakReference.get().showErrorLayout();
            }

            if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
                mFragmentWeakReference.get().showErrorLayout();
            }
        }

    }

    @Override
    public void onError(Throwable e) {
        if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
            mActivityWeakReference.get().removeProgressDialog();
        }
        if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
            mFragmentWeakReference.get().removeProgressDialog();
        }
        error(null);
    }

    @Override
    public void onComplete() {
        if (mActivityWeakReference != null && mActivityWeakReference.get() != null) {
            mActivityWeakReference.get().removeProgressDialog();
        }
        if (mFragmentWeakReference != null && mFragmentWeakReference.get() != null) {
            mFragmentWeakReference.get().removeProgressDialog();
        }
    }
}


例子:

BaseObserver observer = new BaseObserver<BaseResult<List<CategoryVO>>>(this){
            @Override
            public void success(BaseResult data) {
                super.success(data);
                Log.d("aaa", "aaaa");
                CategoryAdapter adapter = new CategoryAdapter(getChildFragmentManager(), mActivity);
                adapter.setData((List<CategoryVO>) data.getData());
                mViewPager.setAdapter(adapter);
                mTabLayout.setupWithViewPager(mViewPager);
            }

            @Override
            public void error(BaseResult data) {
                super.error(data);
            }
        };
        mDisposable.add(observer);
        UtilRetrofit.getInstance().create(Api.class).category().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer);

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市颇象,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌并徘,老刑警劉巖遣钳,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異麦乞,居然都是意外死亡蕴茴,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門姐直,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倦淀,“玉大人,你說我怎么就攤上這事声畏∽策矗” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵插龄,是天一觀的道長能扒。 經(jīng)常有香客問我,道長辫狼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任辛润,我火速辦了婚禮膨处,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砂竖。我一直安慰自己真椿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布乎澄。 她就那樣靜靜地躺著突硝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪置济。 梳的紋絲不亂的頭發(fā)上解恰,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天锋八,我揣著相機(jī)與錄音,去河邊找鬼护盈。 笑死挟纱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腐宋。 我是一名探鬼主播紊服,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胸竞!你這毒婦竟也來了欺嗤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卫枝,失蹤者是張志新(化名)和其女友劉穎煎饼,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剃盾,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腺占,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了痒谴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衰伯。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖积蔚,靈堂內(nèi)的尸體忽然破棺而出意鲸,到底是詐尸還是另有隱情,我是刑警寧澤尽爆,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布怎顾,位于F島的核電站,受9級特大地震影響漱贱,放射性物質(zhì)發(fā)生泄漏槐雾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一幅狮、第九天 我趴在偏房一處隱蔽的房頂上張望募强。 院中可真熱鬧,春花似錦崇摄、人聲如沸擎值。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鸠儿。三九已至,卻和暖如春厕氨,著一層夾襖步出監(jiān)牢的瞬間进每,已是汗流浹背汹粤。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留品追,地道東北人玄括。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像肉瓦,于是被迫代替她去往敵國和親遭京。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,283評論 25 707
  • 一.榜單介紹 排行榜包括四大類: 單一框架:僅提供路由泞莉、網(wǎng)絡(luò)層哪雕、UI層、通信層或其他單一功能的框架 混合開發(fā)框架:...
    偉子男閱讀 5,244評論 0 161
  • 大哥篇 “小伙鲫趁,打球不斯嚎,” “打唄,找個臺子挨厚”てВ” “打不錯啊,是不是練過疫剃《ひ撸” “沒,自己瞎玩巢价∩螅” “呦,你還挺謙虛...
    宇鍋鍋GN閱讀 305評論 1 2
  • 抬頭看天的時候凌唬,好像總會不自覺的笑起來
    浮凌閱讀 276評論 0 0
  • 我愿做一只海鷗 暫棲你的桅桿陪你漂洋過海 像哨兵一樣掠過無垠的海面 偵查每一片可疑的魚群 浮蕩幽幽的海水 探聽深絕...
    蒙山小道閱讀 153評論 2 0