Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava


Retrofit,因为其简单与出色的性能,也是受到很多人的青睐,但是他和以往的通信框架还是有点区别,不过放心,因为他本身还是挺简单的,所有我相信你看完这篇文章,对基本的请求是没什么问题的,其实现在网上这样的文章也有很多了,好了,那我们直接开车吧!

一.相关资料

二.square

square这家公司开源了很多非常优秀的项目,所有拿出来表示一家对他们这帮有开源精神的工程师表达

一下敬意,比如有这些项目:

更多项目可以自己去他们的组织里官网下:https://github.com/square

三.准备工作

我们要使用Retrofit2.0,肯定要先集成进去,把项目这么一新建——RetrofitSample,然后我们看他的Github上,支持三种使用方式,这就没必要多说,各位看官想怎么添加就怎么添加

<dependency>
  <groupId>com.squareup.retrofit2</groupId>
  <artifactId>retrofit</artifactId>
  <version>2.1.0</version>
</dependency>
  • Gradle:
compile 'com.squareup.retrofit2:retrofit:2.1.0'

这里我们就直接用Gradle配置了,毕竟这样最简单,当然,我们配合OkHttp3更加的好用,所以添加源

compile 'com.squareup.okhttp3:okhttp:3.3.1'

这里可别忘了添加网络权限哦!

<uses-permission android:name="android.permission.INTERNET"/>

四.定义接口

我们要想学会使用,最佳的选择肯定是阅读官方的文档,第一句就是

“Retrofit turns your HTTP API into a Java interface”

需要我们定义一个接口,好的,那我们就依葫芦画瓢,写一个接口, 这里一定要记住哦,这个接口写起来是有一定的规范的,我们先看接口

这是Gank的接口,那我们应该怎么去写我们本地的接口呢,这是我们的Json

我们来定义一下我们的接口类,我们取名为GnakApi

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;

public interface GnakApi {

    @GET("api/data/Android/10/1")
    Call<ResponseBody> getAndroidInfo();
}

仔细分析这个接口的定义,其实,这个接口我们可用这样去拆分

前面的baseUrl我们等一下直接定义,后面的,我们才是定义接口,我现在不需要返回值,所以我直接传了一个ResponseBody,而上面,我用GET请求,直接请求了api/data/Android/10/1,这样就能和我们的baseUrl拼接了,而后面的参数如果我们要改变的话,那接口方法就要传参了,这个我们等下来讲,再看下我们文档上的接口定义

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

这个是文档上提供的例子,我们可用发现,他同样的是GET请求,只不过他的返回值是一个List,类型是repo,repo就是他的实体类,传了一个path是一个参数,user的参数,这样也同样的可以和他的baseUrl拼接了他的baseUrl是什么呢,我们等下再说

五.简单请求

接口定义好了之后,我就开始请求了,这里我在布局里面写一个button做点击事件,再写一个textview做返回结果的呈现

    <Button
        android:id="@+id/btn_requet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/button_bg"
        android:text="请求"
        android:textAllCaps="false"
        android:textColor="@android:color/white"/>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

好,那我们要怎么做呢?继续看文档

The Retrofit class generates an implementation of the GitHubService interface.

这里说直接把Retrofit的接口改造成一个类,那需要怎么做呢?首先,我们要创建一个Retrofit

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://gank.io/")
                .build();

这里大家就看到我们的baseUrl了,就是我们Gank接口的前缀,我们现在有了retrofit,通过他的create方法就可以创建我们的接口对象了

 GnakApi api = retrofit.create(GnakApi.class);

这里虽然是返回一个GnakApi,但是通过源码我们知道,这里的create实际上是通过代理的方式拿到的,可以看下

  public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, Object... args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

当然,这里不做深入的了解,我们现在就直接去调用我们的接口方法,他返回的就是一个Call

Call<ResponseBody> call = api.getAndroidInfo();

到这里,你会很奇怪,我去,怎么和okHttp这么像啊,如果单纯从简单请求来看,确实有一丢丢像,但是别急,Retrofit可没这么简单,我们又了call之后就直接请求了,一般我们都是异步请求

call.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        try {
              String result = response.body().string();
              Log.i(TAG, result);
              tv_result.setText(result);
            } catch (IOException e) {
              e.printStackTrace();
        }
    }
              @Override
              public void onFailure(Call<ResponseBody> call, Throwable t) {

              }
          });

那我们直接点,运行一下

恩,可以看到,已经成功的请求到了结果了,这就是Retrofit的无参简单请求了,但是这里我们其实还可以做点文章,Retrofit + OkHttp + Gson更配哦,那我们添加Gson的Jar之后我们写一个实体类,也就是我们这个接口的javaBean,这里我使用的解析插件是Gsonformat

GankBean


import java.util.List;

public class GankBean {

    private boolean error;
    private List<ResultsBean> results;

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public List<ResultsBean> getResults() {
        return results;
    }

    public void setResults(List<ResultsBean> results) {
        this.results = results;
    }

    public static class ResultsBean {
        /**
         * _id : 5827f41b421aa911d3bb7ecb
         * createdAt : 2016-11-13T13:03:23.38Z
         * desc : 独立全端开发的开源小作:简诗 2.0
         * images : ["http://img.gank.io/b6be7a85-4035-437f-9521-65593fdbc48e"]
         * publishedAt : 2016-11-14T11:36:49.680Z
         * source : web
         * type : Android
         * url : https://www.v2ex.com/t/320154
         * used : true
         * who : wingjay
         */

        private String _id;
        private String createdAt;
        private String desc;
        private String publishedAt;
        private String source;
        private String type;
        private String url;
        private boolean used;
        private String who;
        private List<String> images;

        public String get_id() {
            return _id;
        }

        public void set_id(String _id) {
            this._id = _id;
        }

        public String getCreatedAt() {
            return createdAt;
        }

        public void setCreatedAt(String createdAt) {
            this.createdAt = createdAt;
        }

        public String getDesc() {
            return desc;
        }

        public void setDesc(String desc) {
            this.desc = desc;
        }

        public String getPublishedAt() {
            return publishedAt;
        }

        public void setPublishedAt(String publishedAt) {
            this.publishedAt = publishedAt;
        }

        public String getSource() {
            return source;
        }

        public void setSource(String source) {
            this.source = source;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public boolean isUsed() {
            return used;
        }

        public void setUsed(boolean used) {
            this.used = used;
        }

        public String getWho() {
            return who;
        }

        public void setWho(String who) {
            this.who = who;
        }

        public List<String> getImages() {
            return images;
        }

        public void setImages(List<String> images) {
            this.images = images;
        }
    }
}

用Gson是一键生成的,所以还是很方便

六.正常请求

我们做一个和官网一样的例子,实体类GankBean已经有了,那我们重新修改一下接口,让他返回这个实体类

import retrofit2.Call;
import retrofit2.http.GET;

public interface GnakApi {

    @GET("api/data/Android/10/1")
    Call<GankBean> getAndroidInfo();
}

去用的时候前面没有什么变化,只是返回的是实体类罢了

Call<GankBean> call = api.getAndroidInfo();

那我们异步的话,就很简单了

//异步
call.enqueue(new Callback<GankBean>() {
    @Override
    public void onResponse(Call<GankBean> call, Response<GankBean> response) {
        GankBean.ResultsBean bean = response.body().getResults().get(0);
        tv_result.setText(
                "_id:" + bean.get_id() + "\n"
                        + "createdAt:" + bean.getCreatedAt() + "\n"
                        + "desc:" + bean.getDesc() + "\n"
                        + "images:" + bean.getImages() + "\n"
                        + "publishedAt:" + bean.getPublishedAt() + "\n"
                        + "source" + bean.getSource() + "\n"
                        + "type:" + bean.getType() + "\n"
                        + "url: " + bean.getUrl() + "\n"
                        + "who:" + bean.getWho());
    }

    @Override
    public void onFailure(Call<GankBean> call, Throwable t) {

    }
});

这里就可以直接get出我们想要的值了吗?答案是否定的,我们运行之后可以看到这样一行错误

IllegalArgumentException: Unable to create converter for class com.liuguilin.retrofitsample.GankBean

下面该有一条更加重要的信息

Could not locate ResponseBody converter for class com.liuguilin.retrofitsample.GankBean.

这里很直观的说明,不能创建一个转换器,我擦,那怎么办?通过看文档,我们知道,我们需要去配置一个Gson,并不是我们的google.gson,我们添加源

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

单独说这个错误是因为我的学生很多都碰到过,所以这里提一下,然后我们配置一行

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://gank.io/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

现在运行就没问题了

恩,到这里,我们的基本请求就是这个样子,是不是很简单,我们只要前期配置好,并且根据api定义好接口,其他的都变得很方便了,配合Gson,那请求完了就可以直接拿值了,加上比较火的Dagger2注解,代表会变得十分的感人的,简洁,高效。

其实讲到这里,大家对他就已经有了一定的了解了,我们现在继续跟着文档走,来说下他的一些特性

七.Get的动态参数

大家都知道,我们的url大多数是拼接的,就像我们查询天气的接口,肯定是动态传一个城市的名字,对吧,这里我们换一个接口,就用天气的接口

通过官网我们可用得知我们的接口是这样的

这里我们做一个简单的案例,默认cityname是深圳,我们就去拼接我们的key,那我们接口要怎么定义呢,我们写一个WeatherApi:

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface WeatherApi {

    @GET("onebox/weather/query?cityname=深圳")
    Call<WeatherDataBean> getWeather(@Query("key") String key);
}

这里我们可以看到,我们Get还是把我们的连接后半段传进去,但是这里最后拼接的时一个key,所以在传参的前面加上Query,如果你想两个参数,还有一个城市的话,你就多加一个参数咯,我们现在初始化一下

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://op.juhe.cn/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        api = retrofit.create(WeatherApi.class);

好的,拿到我们的接口对象就去用吧

Call<WeatherDataBean> call = api.getWeather("4ea58de8a7573377cec0046f5e2469d5");
//异步
call.enqueue(new Callback<WeatherDataBean>() {
    @Override
    public void onResponse(Call<WeatherDataBean> call, Response<WeatherDataBean> response) {
        String info = response.body().getResult().getData().getRealtime().getWeather().getInfo();
        tv_result.setText("深圳天气:" + info);
    }

    @Override
    public void onFailure(Call<WeatherDataBean> call, Throwable t) {

    }
});

这里的WeatherDataBean实在是数据太多了,所以我就没有显示出来,有需要的我会在本文的最后提供Sample的,这里我们请求,数据太多,我就直接请求一个了,来看运行之后的结果:

八.Get参数请求

上面的Get方法是一般的接口会这样做,但是有些请求,是有问题的,比如我们最上面的这个接口

他并没有像cityname或者key这样的名字,而是直接传参,其实他的参数含义是

 //后面三个参数
 //Android可接受参数  | Android | iOS | 休息视频 | 福利 | 前端 | App
 //count 最大 50
 //page  是页数

这样的类型接口,我们一般是怎么去定义接口的呢?我们改造一下GankApi,这里我就直接传page了

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface GnakApi {

    @GET("api/data/Android/10/{page}")
    Call<GankBean> getAndroidInfo(@Path("page") int page);
}

可以看到,这里我们用大括号做占位符,然后用path关键字,一定要对应哦,其他的都差不多,紧接着我们请求

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://gank.io/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();
api = retrofit.create(GankApi.class);

这样拿到我们的接口对象后直接请求

api.getAndroidInfo(1).enqueue(new Callback<GankBean>() {
    @Override
    public void onResponse(Call<GankBean> call, Response<GankBean> response) {
        tv_result.setText(response.body().getResults().get(0).getDesc());
    }

    @Override
    public void onFailure(Call<GankBean> call, Throwable t) {

    }
});

可以运行看到,依旧是可以拿到我们想要的值的,说明我们这个也是可以的

九.Get参数拼接

这个又是什么呢,我们把天气的api改一下你就知道了

import java.util.Map;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.QueryMap;

public interface WeatherApi {

    @GET("onebox/weather/query?")
    Call<WeatherDataBean> getWeather(@QueryMap Map<String, String> params);
}

仔细看我这里GET后面传的并没有像cityname之类的参数,但是我这里有一个QueryMap ,传的是键值对,这样我们怎么去用呢?可以这样:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://op.juhe.cn/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
api = retrofit.create(WeatherApi.class);

这里倒是没什么改变的,我们主要看接口传递的对象:

Map<String, String> params = new HashMap<>();
params.put("cityname", "深圳");
params.put("key", "4ea58de8a7573377cec0046f5e2469d5");
api.getWeather(params).enqueue(new Callback<WeatherDataBean>() {
    @Override
    public void onResponse(Call<WeatherDataBean> call, Response<WeatherDataBean> response) {

    }

    @Override
    public void onFailure(Call<WeatherDataBean> call, Throwable t) {

    }
});

这里我们可以看到传map,然后map去put参数,这样最后请求的url就是

十.Post

POST请求的话,因为没有接口,所以我简单说一下,我也相信,你看到这里,get了解了post也相应的知道点,不过别急,我们还是会很详细的讲

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;

public interface PostApi {

    @POST("user/new")
    Call<Result> postUser(@Body User user);
}

这里POST的地址和之前的get也是一样的,这里返回一个Result是我们自家定义的结果,Body是表示参数,我需要一个User,那我们的User就是

public class User {

    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

而我们的Result:

public class Result {

    private int yes;
    private int no;

    public int getYes() {
        return yes;
    }

    public void setYes(int yes) {
        this.yes = yes;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }
}

这两个都是没什么东西的,然后我们就可以直接去看怎么调用了

User user = new User();
    user.setId(1);
    user.setName("lgl");
    api.postUser(user).enqueue(new Callback<Result>() {
        @Override
        public void onResponse(Call<Result> call, Response<Result> response) {
            if (response.body().getYes() == 0) {
                Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<Result> call, Throwable t) {

        }
    });

我再这里传了一个user进去,细节不为过就是id和name,如果请求成功,那就返回0,失败就是1,这里服务端定义,这样我们就POST完成了

十一.Post提交表单

根据官网上的例子,还有一个更新用户的方法,用的就是提交表单

@POST("user/edit")
Call<Result> editUser(@Field("id") int id, @Field("name") String name);

OK,我们用到的关键字是Field,这样去定义,然后直接调用这个方法

api.editUser(1, "liuguilin").enqueue(new Callback<Result>() {
        @Override
        public void onResponse(Call<Result> call, Response<Result> response) {
            if (response.body().getYes() == 0) {
                Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onFailure(Call<Result> call, Throwable t) {

        }
    });

这样就把表单提交了,是不是很方便呢

最后还有一个PUT,他是多种文件类型上传,比如文件,图片,这里大家参考下官方文档

当然还有修改我们的Headers,这个很简单,看例子

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();

这是官网的例子,但是你只需要添加Headers参数就可以穿了,而且因为他的参数时一个数组,你可以穿多个

按道理讲到这里算是完成了,我这里稍微的带点例子,讲下RxJava,因为我自己也不是很熟,所以我就讲我了解的这一块就好了

十二 Retrofit2.0+ RxJava

RxJava使用起来会让我们的代码更加的简洁,高效,那他和Retrofit2.0又会碰到什么样的激情呢?欢迎大家收看今天的人与自然……额 …跑题了,我们先做一些准备,主要是什么呢,根据官网来看,需要添加

    //适配器
    compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
    //RxJava
    compile 'io.reactivex:rxjava:1.1.6'
    //RxAndroid
    compile 'io.reactivex:rxandroid:1.2.1'

地址

这里我举一个最常见的例子来说明。那就是登录,登录成功后获取到user_id,再去请求用户信息,这里应该是两个请求对吧,我们先去写好接口,这里我们先用常规的方法去获取:

    @POST("user/login")
    Call<User> login(@Field("username") String user, @Field("password") String password);

    @GET("user/info")
    Call<User> getUser(@Query("id") String id);

这里的两个接口,一个是登录,传参用户名和密码,还有一个是用id去查找用户信息的,那我们继续

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("baseUrl")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
 api = retrofit.create(PostApi.class);

这里我们需要增加addCallAdapterFactory为我们后面的Rx做准备,然后我们调用两次

api.login("liuguilin", "748778890").enqueue(new Callback<User>() {
    @Override
    public void onResponse(Call<User> call, Response<User> response) {
        if (response.isSuccessful()) {
            String id = response.body().getUser_id();
            api.getUser(id).enqueue(new Callback<User>() {
                @Override
                public void onResponse(Call<User> call, Response<User> response) {

                    Toast.makeText(MainActivity.this, "id:" +
                                    response.body().getId()
                                    + "name:" + response.body().getName(),
                            Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(Call<User> call, Throwable t) {

                }
            });
        }
    }

    @Override
    public void onFailure(Call<User> call, Throwable t) {

    }
});

这样写代码是不是有点臃肿,别急,我们看看RxJava的写法,我们这里需要重新定义两个接口了

    @POST("user/login")
    rx.Observable<User> loginForRX(@Body User user);

    @GET("user/info")
    rx.Observable<User> getUserForRX(@Query("id") String id);

这里的都是伪代码,注意看使用方法

api.loginForRX(new User("liuguilin", "748778890")).flatMap(new Func1<User, Observable<User>>() {
    @Override
    public Observable<User> call(User user) {
        return api.getUser(user.getUser_id());
    }
}).subscribe(new Action1<User>() {
    @Override
    public void call(User user) {
        Toast.makeText(MainActivity.this, "name:" + user.getName(), Toast.LENGTH_SHORT).show();
    }
});

这就是比较简洁的写法了,RxJava作为链式的表达式,响应式的操作还是很不错的,我会在我后面的博客继续深入的剖析,这里就不做太深入的了解了,因为感觉自己还没有到家吧,所以只是提一提,好了,到这里算是Ok了,你的Retrofit2.0学会了吗?

群:555974449

Sample:http://download.csdn.net/detail/qq_26787115/9683939

时间: 2024-10-27 16:17:22

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava的相关文章

热门技术探讨:学习Web 2.0的方向盘

web 历史很重要.对一个技术的学习也应当从历史出发,通过其在时间形成历史的流变,得以知晓现状,甚至能够预知未来. 那Web 1.0是什么呢? 他们说,记得静态HTML的WWW时代么? (那个时代的WWW应用.人们的Web体验.对社会的影响如何?) 那么动态HTML和静态HTML下的Web相比,是多少版本?1.5?对了,他们是真这么叫的. (在效果和影响上,与1.0相比,扩展和加深多少?) 要呈现的数据存储在数据库中,通过Web服务端的程序,应用户的请求,取出数据,加上事先设计的模板,动态的生成

《CUDA高性能并行计算》----0.2 学习CUDA的“须知”

本 节 书 摘 来 自 华 章 出 版 社 <CUDA高性能并行计算> 一 书 中 的 第0章,第0.2节, 作 者 CUDA for Engineers: An Introduction to High-Performance Parallel Computing[美] 杜安·斯托尔蒂(Duane Storti)梅特·尤尔托卢(Mete Yurtoglu) 著,苏统华 项文成 李松泽 姚宇鹏 孙博文 译 , 更 多 章 节 内 容 可 以 访 问 云 栖 社 区 "华 章 计 算

JavaScript中为什么null==0为false而null大于=0为true(个人研究)_javascript技巧

生活中我们在不停的编写代码,写着JavaScript,很少有时间进行概念上的研究.我呢,今天闲来没啥事,研究了一下有关"null"和"0"的关系.希望大家看完了能有所收获. 复制代码 代码如下: alert(null>=0) 复制代码 代码如下: 上面的代码会弹出什么来呢?False?True?其实是true.那么是为什么呢?为什么"null>=0"为true呢?null>=0的时候,强转为数字类型.在进行null>=0比

Oracle 11.2.0.1升级到11.2.0.3

Oracle  11.2.0.1升级到11.2.0.3 最近听了李光老师的关于oracle的升级公开课,深有感悟,之前一直想自己测试的,没有下定决心,这几天自己在虚拟机上测试了一下,测试的过程如下,当然这个只是一些基本的步骤,实际的生产环境我想比这个复杂的多了,但是不用急,慢慢来,循序渐进吧... 由于blog的文档结构没有办法显示,所以这里我截取我的文档结构图: 数据库情况 单实例非ASM存储 ORACLE_SID : orcl ORACLE_HOME: /u01/app/oracle/pro

PATCHSET 10.1.0.3&amp;amp;amp;9.2.0.5

patchset  3761843   for   oracle 10.1.0.3  升级10.1.0.2 到10.1.0.3   patchset  3501955   for   oracle  9.2.0.4  升级到 9.2.0.5  不过升级后还是要打和alert#68 相关的那个PATCH 3811906  这样才完整文件名称为10.1.0.3  p3761843_10103_LINUX.zip  551M9.2.0.5   p3501955_9205_LINUX.zip   313

IE5.0、IE5.5、IE6.0、IE7.0、FF1.5、FF2.0兼容CSS Hack代码范例

css IE7.0简体中文正式版终于发布了,对于我等常和网页打交道的人来说网页兼容性问题也随之而来了.IE7.0有一个显著的改变就是支持!important了,是件好事情,但是也给广大的在IE6时代使用!important来区分处理IE和FF的网页制作者带来了不少问题,Noker也遇到了这个问题,所以翻阅网上资料,写了下面这个能够兼容现今大多数主流浏览器,覆盖绝大多数用户的Hack代码,发布在自己的论坛上,供大家查看,研究,取用.如有相关问题欢迎跟贴探讨,谢谢! 兼容浏览器版本:IE5.0,IE

关于asp.net 1.0升级到asp.net 2.0时发现的一个有趣的问题

asp.net|问题     今天终于把原来的asp.net 1.0程序升级到asp.net 2.0了,vs 2005带有转换向导,一切自动化,操作比较方便.等它自动转换后,突然发现在App_Code文件夹里多了几个比较奇怪的文件都是stub开头的,并在一个mi开头的文件夹中(具体名称因为删除了,忘记了),因为原来根本就没有这些.cs文件,打开一看,原来都是抽象类,有几个还有抽象方法和共有字段.经过查看,才发现,原来在asp.net 1.0中有几个页面后置文件即.aspx.cs文件,里面有pub

Visual Studio-Visual Studio 2010中的实体框架4.0和WCF数据服务4.0

在诸多新改进之中,Visual Studio 2010 引入了用户期待已久的实体框架 4.0 和 WCF 数据服务 4.0(以前称为 ADO.NET 数据服务),这两项功能综合起来,简化了您建立数据模型.使用数据和生成数据的方式. 实体框架 4.0 (EF 4.0) 致力于启用和简化两种主要方案:以域为中心的应用程序开发和传统以数据为中心的"基于数据的窗体设计".它引入了诸如模型优先开发等功能(该功能允许您创建模型并为您生成自定义 T-SQL):对持久化透明的支持:外键:延迟加载以及实

usb3.0能不能完全兼容usb2.0

  usb3.0是usb2.0的升级版本,所以在usb2.0的基础上,usb3.0是完全兼容usb2.0.但是前提是你的电脑主板必须支持usb3.0,其次就是你的电脑所使用的设备支持usb3.0,比如你在硬件方面不支持usb3.0的话,那么就不能实现完全兼容usb3.0的情况. 在usb3.0上面它的结构是一样的,插口还是和usb2.0一样的,而usb3.0只是提高了数据传输速度.当你的电脑如果只能兼容usb2.0的话,你插上usb3.0的u盘它是能兼容usb3.0,但是usb3.0的传输速度没