1,其实早就想把这些东西给封装封装的,一直没有时间,今天刚好项目进入到测试阶段了,Bug同事在哪儿测试的飞起,但发现提bug的尽然是我(得意脸),然后上午把ios的包测试了一下,顺便把服务器给测挂了(别问我是怎么做到的),现在服务器的同事还在拿着刀满街找我呐。好了不扯了,就想标题写了,一直想把这一块揉在一起写写,那就趁这个机会吧。

先看看今天我们要实现的效果:

2,有些童鞋就很气愤了,麻蛋,裤子都脱了,你给我看这个!!!!

   其实我也想多写点的啊,还想把App下载写上呢,没事,我们慢慢一点点的来,,先来看一下我们接口的数据吧

{
"code": 200,
"message": "",
"data": {
"code": "1.1.0",
"size": "8.6M",
"des": "1.【新增】自动更新\\r\\n2.【修改】部分ProgressBar替换为SVG\\r\\n3.【修改】Gank板块部分改动\\r\\n"
}
}

  可以看到,这是一个标准的接口数据,外部包含 code、message、data三大门神,这样我们封装Response就很好解决了。

  看一下我们的BaseResponse类,很简单,没有什么讲的

  BaseResponse.java

package com.qianmo.myview2.response;

/**
* Created by wangjitao on 2016/11/8 0008.
* 数据返回类类
*/
public class BaseResponse<T> {
private int code;
private String message;
private T data; public T getData() {
return data;
} public void setData(T data) {
this.data = data;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
}
}

  再看一下我们这次的功能,就是一个简单的网络请求,判断当前app版本和服务器上的版本,从而判断是否是最新的,看到这里的同学可能就很疑惑了,麻蛋,不是说好了是封装封装嘛,为什么到现在还在说功能,嗯,阿呆哥哥只是想从本质上对比一下如果我们使用传统的MVC去写的话该是怎么写的啊,相信现在很多同学已经在脑海中已经有了代码了,不过我猜你们的Activity中的代码会很多(奸笑脸),好吧,我前面的博客也介绍了MVP模式,现在我们是要把MVP运用在项目里面,所以,我们就要开始封装基类了!!

3 ,封装

①BaseView

我们知道在MVP模式中我们的V是和我们用户界面的UI有关的,不管是控件的隐藏和显示,还是控件大小的改变都是我们的V来处理的,所以这里我们只是写了个简单的夜间模式的UI改变的方法、还有展示错误信息的方法,很简单

package com.qianmo.myview2.base;

import android.view.View;

/**
* Created by wangjitao on 2016/11/8 0008.
* 一般的Activity中要用到View操作无非是显示加载框、影藏加载框、显示出错信息、显示当数据为空的时候的view之类的
*/
public interface BaseView { void showError(String msg); void useNightMode(boolean isNight); }

  

②BasePresenter

P在MVP架构中是主要用于逻辑处理的,所以一是我们最经常要写的,看一下代码,就是AttachView和DetachView(这也没什么好解释的)

package com.qianmo.myview2.base;

/**
* Created by wangjitao on 2016/11/8 0008.
* MVP框架的简单封装 P处理层
*/
public interface BasePresenter<T extends BaseView> { void attachView(T view); void detachView();
}

③App

这个类一般用于初始化一些数据,如屏幕的信息之类的和Activity的简单的管理啊,还有一些第三方SDK的初始化

package com.qianmo.myview2;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager; import java.util.HashSet;
import java.util.Set; /**
* Created by wangjitao on 2016/11/8 0008.
*/
public class App extends Application { private static App instance;
private Set<Activity> allActivities; public static int SCREEN_WIDTH = -1;
public static int SCREEN_HEIGHT = -1;
public static float DIMEN_RATE = -1.0F;
public static int DIMEN_DPI = -1; public static synchronized App getInstance() {
return instance;
} @Override
public void onCreate() {
super.onCreate(); instance = this; getScreenSize();
} /**
* 初始化屏幕宽高
*/
public void getScreenSize() {
WindowManager windowManager = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
Display display = windowManager.getDefaultDisplay();
display.getMetrics(dm);
DIMEN_RATE = dm.density / 1.0F;
DIMEN_DPI = dm.densityDpi;
SCREEN_WIDTH = dm.widthPixels;
SCREEN_HEIGHT = dm.heightPixels;
if (SCREEN_WIDTH > SCREEN_HEIGHT) {
int t = SCREEN_HEIGHT;
SCREEN_HEIGHT = SCREEN_WIDTH;
SCREEN_WIDTH = t;
}
} /**
* 添加activity
*/
public void addActivity(Activity act) {
if (allActivities == null) {
allActivities = new HashSet<>();
}
allActivities.add(act);
} /**
* 移除activity
*/
public void removeActivity(Activity act) {
if (allActivities != null) {
allActivities.remove(act);
}
} /**
* 退出app
*/
public void exitApp() {
if (allActivities != null) {
synchronized (allActivities) {
for (Activity act : allActivities) {
act.finish();
}
}
}
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
} /**
* 这还有一系列的第三方SDK的初始化
*/
}

④BaseActivity

这个貌似是最重要的,这里我们考虑到5.0一下的机器切换Activity比较丑,所以写了下切换的动画,,然后就是一系列的初始化,直接贴出来吧

package com.qianmo.myview2.base;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View; import com.qianmo.myview2.App;
import com.qianmo.myview2.R; import butterknife.Unbinder;
import butterknife.ButterKnife; /**
* Created by wangjitao on 2016/11/8 0008.
* 基类Activity的封装
* 一般使用mvp模式的话会在BaseActivity中进行P和V的初始化绑定
*/
public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView {
protected T mPresenter;
protected Activity mContext;
private Unbinder mUnbinder; public enum TransitionMode {
LEFT, RIGHT, TOP, BOTTOM, SCALE, FADE
} protected void onCreate(@Nullable Bundle savedInstanceState) {
if (toggleOverridePendingTransition()) {
switch (getOverridePendingTransitionMode()) {
case LEFT:
overridePendingTransition(R.anim.left_in, R.anim.left_out);
break;
case RIGHT:
overridePendingTransition(R.anim.right_in, R.anim.right_out);
break;
case TOP:
overridePendingTransition(R.anim.top_in, R.anim.top_out);
break;
case BOTTOM:
overridePendingTransition(R.anim.bottom_in, R.anim.bottom_out);
break;
case SCALE:
overridePendingTransition(R.anim.scale_in, R.anim.scale_out);
break;
case FADE:
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
break;
}
} super.onCreate(savedInstanceState);
setContentView(getLayout()); mUnbinder = ButterKnife.bind(this);
mContext = this; createPresenter(); if (mPresenter != null)
mPresenter.attachView(this);
App.getInstance().addActivity(this);
initEventAndData();
} @Override
protected void onStart() {
super.onStart(); } @Override
protected void onDestroy() {
super.onDestroy();
if (mPresenter != null)
mPresenter.detachView();
mUnbinder.unbind();
App.getInstance().removeActivity(this);
} protected void setToolBar(Toolbar toolbar, String title) {
toolbar.setTitle(title);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
} protected abstract int getLayout(); protected abstract void initEventAndData(); protected abstract boolean toggleOverridePendingTransition(); protected abstract TransitionMode getOverridePendingTransitionMode(); protected abstract void createPresenter();
}

⑤ BaseRecyclerViewAdapter

package com.qianmo.myview2.base;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.balysv.materialripple.MaterialRippleLayout;
import com.qianmo.myview2.R; import java.util.List; /**
* Created by wangjitao on 2016/11/7 0007.
* 对简单的recycleview进行简单的封装
*/
public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
private Context context;
private LayoutInflater inflater;
private List<T> datas;
private int layoutId;
protected OnItemClickListner onItemClickListner;//单击事件
protected OnItemLongClickListner onItemLongClickListner;//长按单击事件
private boolean clickFlag = true;//单击事件和长单击事件的屏蔽标识 public BaseRecyclerViewAdapter(Context context, List<T> datas, int layoutId) {
this.context = context;
this.datas = datas;
this.layoutId = layoutId;
this.inflater = LayoutInflater.from(context);
} @Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
BaseViewHolder holder = new BaseViewHolder(inflater.inflate(layoutId, parent, false));
MaterialRippleLayout.on(holder.getView(R.id.ll_all))
.rippleOverlay(true)
.rippleAlpha(0.2f)
.rippleColor(context.getResources().getColor(R.color.colorAccent))
.rippleHover(true)
.create();
return holder;
} @Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
bindData(holder, datas.get(position), position);
} @Override
public int getItemCount() {
return datas == null ? 0 : datas.size();
} protected abstract void bindData(BaseViewHolder holder, T data, int position); public void setOnItemClickListner(OnItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
} public void setOnItemLongClickListner(OnItemLongClickListner onItemLongClickListner) {
this.onItemLongClickListner = onItemLongClickListner;
} public interface OnItemClickListner {
void onItemClickListner(View v, int position);
} public interface OnItemLongClickListner {
void onItemLongClickListner(View v, int position);
}
}

⑥ BaseViewHolder

package com.qianmo.myview2.base;

import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View; /**
* Created by wangjitao on 2016/11/7 0007.
* 万能的Viewholder
*/
public class BaseViewHolder extends RecyclerView.ViewHolder { private SparseArray<View> views; public BaseViewHolder(View view) {
super(view);
this.views = new SparseArray<>();
} public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
} public View getRootView() {
return itemView;
}
}

由于上一篇介绍了怎么封装RecycleView的Adapter,在这里就不在废话了  

4,好了东西都封装好了,看一下我们在实际功能中怎么写吧,由于我们上面的功能,我们要实现一个简单的版本判断,由于要使用网络,这里我打算使用Retrofit+RxJava,但是还没有封装好,就直接拿没封装的直接用了,这里创建mvp模式的话要创建好多个接口啊 ,所以推荐是用MVPHelper这个插件,挺好用的  ,好了,先看一下我们的MainContract

package com.qianmo.myview2.contract;

import com.qianmo.myview2.base.BasePresenter;
import com.qianmo.myview2.base.BaseView;
import com.qianmo.myview2.bean.VersionBean; /**
* Created by wangjitao on 2016/11/8 0008.
* 首页逻辑处理
*/
public class MainContract { public interface View extends BaseView {
//View效果就是展示下载进度框
void showUpdateDialog(VersionBean bean); void showProgressDialog(); void DissProgressDialog(); void ShowToast(String message);
} public interface Presenter extends BasePresenter<View> {
//一般在首页我们会进行一个版本的更新(功能)
void checkVersion(String currentVersion);
} }

就只是接口的常见,并把这次功能要用到的方法全部抽象出来,

看一下我们Presenter的实现类

MainPresenterImpl.java

package com.qianmo.myview2.presenter;

import android.widget.Toast;

import com.qianmo.myview2.CheckVersionActivity;
import com.qianmo.myview2.MainActivity;
import com.qianmo.myview2.api.AppVersionService;
import com.qianmo.myview2.bean.VersionBean;
import com.qianmo.myview2.contract.MainContract;
import com.qianmo.myview2.response.BaseResponse;
import com.qianmo.myview2.utils.Constant; import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers; /**
* Created by MVPHelper on 2016/11/08
*/ public class MainPresenterImpl implements MainContract.Presenter { private MainContract.View mView; @Override
public void checkVersion(final String currentVersion) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
AppVersionService movieService = retrofit.create(AppVersionService.class); movieService.getVersion()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<BaseResponse<VersionBean>>() {
@Override
public void onStart() {
mView.showProgressDialog();
} @Override
public void onCompleted() {
mView.DissProgressDialog();
} @Override
public void onError(Throwable e) {
mView.DissProgressDialog();
mView.ShowToast("请求出错");
} @Override
public void onNext(BaseResponse<VersionBean> versionBeanBaseResponse) {
if (Integer.valueOf(currentVersion.replace(".", "")) < Integer.valueOf(versionBeanBaseResponse.getData().getCode().replace(".", ""))) {
// mView.showUpdateDialog(versionBean);
//这里表示发现新版本
mView.ShowToast("发现最新版本");
} else {
//表示这就是最新版本
mView.ShowToast("已经是最新版本");
}
}
});
} @Override
public void attachView(MainContract.View view) {
mView = view;
} @Override
public void detachView() {
mView = null;
} }

没有什么好讲解的,其实还可以把presenter层封装一下的,可以在封装成这样的

public class BasePresenter<T extends MvpView> implements Presenter<T> {

    private T mMvpView;

    @Override
public void attachView(T mvpView) {
mMvpView = mvpView;
} @Override
public void detachView() {
mMvpView = null;
} public boolean isViewAttached() {
return mMvpView != null;
} public T getMvpView() {
return mMvpView;
} public void checkViewAttached() {
if (!isViewAttached()) throw new MvpViewNotAttachedException();
} public static class MvpViewNotAttachedException extends RuntimeException {
public MvpViewNotAttachedException() {
super("Please call Presenter.attachView(MvpView) before" +
" requesting data to the Presenter");
}
}
}

  ok,最后看一下我们的Activity

package com.qianmo.myview2;

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast; import com.qianmo.myview2.base.BaseActivity;
import com.qianmo.myview2.bean.VersionBean;
import com.qianmo.myview2.contract.MainContract;
import com.qianmo.myview2.presenter.MainPresenterImpl; import butterknife.BindView; public class CheckVersionActivity extends BaseActivity<MainPresenterImpl> implements MainContract.View, View.OnClickListener {
@BindView(R.id.btn_getVersion)
Button btnGetVersion;
@BindView(R.id.progressBar)
ProgressBar progressBar; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} @Override
protected int getLayout() {
return R.layout.activity_main;
} @Override
protected void initEventAndData() {
btnGetVersion.setOnClickListener(this); } @Override
protected boolean toggleOverridePendingTransition() {
return false;
} @Override
protected TransitionMode getOverridePendingTransitionMode() {
return null;
} @Override
protected void createPresenter() {
mPresenter = new MainPresenterImpl();
} @Override
public void showError(String msg) { } @Override
public void useNightMode(boolean isNight) { } @Override
public void showUpdateDialog(VersionBean bean) { } @Override
public void showProgressDialog() {
progressBar.setVisibility(View.VISIBLE);
} @Override
public void DissProgressDialog() {
progressBar.setVisibility(View.GONE);
} @Override
public void ShowToast(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
} @Override
public void onClick(View view) {
try {
PackageManager pm = getPackageManager();
PackageInfo pi = pm.getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES);
String versionName = pi.versionName;
mPresenter.checkVersion(versionName);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}

  再贴一下布局文件

<?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"
android:background="#ffffff"
> <include
android:id="@+id/toolbar"
layout="@layout/view_toolbar"/> <android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbar"
android:visibility="gone"
> </android.support.v7.widget.RecyclerView> <Button
android:id="@+id/btn_getVersion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="400dp"
android:text="检查版本"
/> <ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"
/>
</RelativeLayout>

  build.gradle

apply plugin: 'com.android.application'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0" defaultConfig {
applicationId "com.qianmo.myview2"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
} dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.0.0'
compile 'com.android.support:design:25.+'
compile 'com.android.support:recyclerview-v7:25.+'
compile 'com.android.support:cardview-v7:25.+'
compile 'com.balysv:material-ripple:1.0.2'
compile 'com.jakewharton:butterknife:8.2.1'
apt 'com.jakewharton:butterknife-compiler:8.2.1'
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
compile 'com.google.code.gson:gson:2.6.2'
}

  好了,这样我们就把MVP简单的封装了,有没有很简单啊,下一篇接着封装Retrofit+Rxjava+Dagger。

see you next time·······

Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(一)的更多相关文章

  1. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)

    1,昨天我们基本上把MVP给封装起来了,今天接着昨天的东西来结合RxJava把Retrofit把网络框架简单的封装一下,先看一下我们今天实现的效果: 哈哈 ,还是昨天的效果,好吧 ,我认错. 2,由于 ...

  2. Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(三)

    1,这一篇博客是和大家一起来封装我们最后的Dagger2,其实之前也写过关于简单的Dagger2,这里是地址,完全没了解的同学可以先去看一下这篇,感谢很多小伙伴一直在耐心的等待这一篇 2,Dagger ...

  3. Android App的设计架构:MVC,MVP,MVVM与架构经验谈

    相关:http://www.cnblogs.com/wytiger/p/5996876.html 和MVC框架模式一样,Model模型处理数据代码不变在Android的App开发中,很多人经常会头疼于 ...

  4. Android App的设计架构:MVC,MVP,MVVM与架构AAAAA

    1. 架构设计的目的1.1 通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合.1.2 这样做的好处是使得程序在开发的过程中,开发人员只需要专注于一点,提高程序开发的效率,并且更容易进行后续 ...

  5. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

  6. okhttputils【 Android 一个改善的okHttp封装库】使用(一)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本文使用的OKHttp封装库是张鸿洋(鸿神)写的,因为在项目中一直使用这个库,所以对于一些常用的请求方式都验证过,所以特此整理下. ...

  7. okhttputils【 Android 一个改善的okHttp封装库】使用(三)

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 这一篇主要讲一下将OkHttpUtils运用到mvp模式中. 数据请求地址:http://www.wanandroid.com/to ...

  8. Android二维码识别 开源项目ZXing的编译

    Android二维码识别 开源项目ZXing的编译 Android端的条形码/二维码识别功能 因为手机端的输入不是很方便,所以条形码/二维码的扫描是一种很有效的解决手段. 比较流行的手机应用中,常用的 ...

  9. Android -- 带你从源码角度领悟Dagger2入门到放弃

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

随机推荐

  1. JavaScript必须了解的知识点总结【转】

    整理的知识点不全面但是很实用. 主要分三块: (1)JS代码预解析原理(包括三个段落): (2)函数相关(包括 函数传参,带参数函数的调用方式,闭包): (3)面向对象(包括 对象创建.原型链,数据类 ...

  2. ZeroMQ接口函数之 :zmq_msg_init_size - 使用一个指定的空间大小初始化ZMQ消息对象

    ZeroMQ 官方地址 :http://api.zeromq.org/4-1:zmq_msg_init_size zmq_msg_init_size(3) ØMQ Manual - ØMQ/3.2.5 ...

  3. strftime 日期时间格式化

    strftime() 函数根据区域设置格式化本地时间/日期,函数的功能将时间格式化,或者说格式化一个时间字符串. size_t strftime(char *strDest,size_t maxsiz ...

  4. 文件编码、charset、sublime编辑器支持GBK等问题

    问题一:如何让sublime3支持GBK 首先打开package control ,然后键入install package进入,搜索ConvertToUTF8安装成功后 打开要查看的GBK文件,点击菜 ...

  5. 【转】安装第三方库出现 Python version 2.7 required, which was not found in the registry

    安装第三方库出现 Python version 2.7 required, which was not found in the registry 建立一个文件 register.py 内容如下. 然 ...

  6. Java实现验证码制作之一Kaptcha验证码

    Kaptcha验证码 是google提供的验证码插件,使用起来相对简单,设置的干扰线以及字体扭曲不易让其他人读取破解. 这里我们需要 导入一个 kaptcha-2.3.jar  下载地址:http:/ ...

  7. 2016huasacm暑假集训训练四 递推_B

    题目链接:http://acm.hust.edu.cn/vjudge/contest/125308#problem/B 题意:给定n个三角形,问最多可以把区域化成多少个部分,这是一个一维空间  一定会 ...

  8. 温故而知新 兼容性较强的轮播器superslide.js

    官网: http://www.superslide2.com/index.html demo: http://www.superslide2.com/demo.html API: http://www ...

  9. finnal 评论 II

    新蜂团队:俄罗斯方块界面设计给人眼前一亮的感觉,很喜欢他们界面的颜色搭配.功能上实现了俄罗斯方块的基本功能,并且没有bug.最重要的是游戏有自己的创新点在里面,很喜欢游戏的瞄准功能.总的来说项目完成的 ...

  10. spring的显示装配bean(1)------通过XML文件装配

    1:spring环境的简单搭建 (1)导入spring相关的jar包. 2:准备要进行装配的Java类 这里给出两个举例类 (1) (2) 3:配置XML文件 (1)在配置文件的顶部声明多个XML模式 ...