Android 搭建网络访问框架(中)

dmzhaoq1
发布于 2021-3-3 09:56
浏览
1收藏

接上篇,我们接着弄自定义Observer

 

六、自定义Observer


  在上面的代码中完成了对OkHttp的优化,OkHttp负责网络访问,使用Retrofit发起网络请求,使用RxJava处理返回结果,在上面只是做了线程的切换和错误码的处理,所以还需要的返回做一个处理,下面在com.llw.network下新建一个observer包,该包下新建一个BaseObserver的抽象类,里面代码如下:

package com.llw.network.observer;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

/**
 * 自定义Observer
 * @author llw
 */
public abstract class BaseObserver<T> implements Observer<T> {

    //开始
    @Override
    public void onSubscribe(Disposable d) {

    }
    
    //继续
    @Override
    public void onNext(T t) {
        onSuccess(t);
    }
    
    //异常
    @Override
    public void onError(Throwable e) {
        onFailure(e);
    }

    //完成
    @Override
    public void onComplete() {

    }

    //成功
    public abstract void onSuccess(T t);
    //失败
    public abstract void onFailure(Throwable e);
}


这里我并没有重写Observer的所有方法,只用了两个,onNext和onError。

 

七、配置网络环境


  在日常开发中,常常会有多个开发环境,比如测试环境、正式环境。他们的区别其实就是前面的地址不同而已,后面的参数都是一样的。举个例子,加入你是Android开发,你面对了两个后台开发,在项目初期后台的服务器都是在自己的电脑上,因此你需要配置他们电脑的ip地址才能去访问他们所写的接口API,普通做法就是对接A的接口时使用A的ip,对接B的接口时使用B的ip,你可能会觉得不就是修改一行代码的事情吗,不麻烦,那假如让你打包出来测试呢?因为一个APP的出现不能不去测试,开发的话要是能信,还要测试干什么?这是我一个测试朋友说的,一时间我竟无法反驳。因此为了避免不断需要我们去根据不同的网络环境打包测试,就体现出来这个网络环境的重要性了,说了这么多也是一个建议,当然你是否采纳取决于自己,起码我是这么做的。

 

在com.llw.network下新建一个environment包。包下新建一个NetworkEnvironmentActivity,然后先不管它,因为还需要配置一些东西才行。在res下创建一个layout文件下,在这个文件夹下创建一个activity_network_environment.xml文件,里面的代码如下:

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

Android 搭建网络访问框架(中) -鸿蒙开发者社区

然后在values下新建一个network_array.xml文件,用于网络配置数组参数,里面的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="environmentName">
        <item>正式</item>
        <item>测试</item>
    </string-array>

    <string-array name="environmentValues">
        <item>1</item>
        <item>2</item>
    </string-array>
</resources>

 

这里我配置了两个环境,一个正式一个测试,实际开发中可能会更多,可根据实际情况进行增减。

 

然后在drawable下新建一个ic_network_settings.xml,这是一个图标,用路径写的。

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="56dp"
    android:height="56dp"
    android:viewportWidth="56"
    android:viewportHeight="56">
    <path
        android:fillColor="#FF000000"
        android:pathData="M8,41.08V2c0,-0.553 -0.448,-1 -1,-1S6,1.447 6,2v39.08C2.613,41.568 0,44.481 0,48c0,3.859 3.14,7 7,7s7,-3.141 7,-7C14,44.481 11.387,41.568 8,41.08zM7,53c-2.757,0 -5,-2.243 -5,-5s2.243,-5 5,-5s5,2.243 5,5S9.757,53 7,53z"/>
    <path
        android:fillColor="#FF000000"
        android:pathData="M29,20.695V2c0,-0.553 -0.448,-1 -1,-1s-1,0.447 -1,1v18.632c-3.602,0.396 -6.414,3.456 -6.414,7.161s2.812,6.765 6.414,7.161V54c0,0.553 0.448,1 1,1s1,-0.447 1,-1V34.891c3.4,-0.577 6,-3.536 6,-7.098S32.4,21.272 29,20.695zM27.793,33c-2.871,0 -5.207,-2.336 -5.207,-5.207s2.335,-5.207 5.207,-5.207S33,24.922 33,27.793S30.664,33 27.793,33z"/>
    <path
        android:fillColor="#FF000000"
        android:pathData="M56,8c0,-3.859 -3.14,-7 -7,-7s-7,3.141 -7,7c0,3.519 2.613,6.432 6,6.92V54c0,0.553 0.448,1 1,1s1,-0.447 1,-1V14.92C53.387,14.432 56,11.519 56,8zM49,13c-2.757,0 -5,-2.243 -5,-5s2.243,-5 5,-5s5,2.243 5,5S51.757,13 49,13z"/>
</vector>

 

然后在strings.xml中增加一个值。

	<string name="network_environment_setting">网络环境设置</string>
    <string name="network_change_tip">您已经更改了网络环境,在您退出当前页面的时候APP将会重启切换环境!</string>

 

 

Android 搭建网络访问框架(中) -鸿蒙开发者社区

下面对网络进行一些配置,在Android9.0及以后版本,默认使用Https访问网络,这导致了不能使用Http,因此要配置允许使用Http,在res下新建一个xml文件夹,在这个文件夹下新建一个network_security_config.xml,里面的代码如下:

 

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

 

然后在这个xml文件夹下再建一个environment_preference.xml文件,里面的代码如下:

 

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

    <ListPreference
        android:defaultValue="1"
        android:entries="@array/environmentName"
        android:entryValues="@array/environmentValues"
        android:icon="@drawable/ic_network_settings"
        android:key="network_environment"
        android:summary="请您选择您需要使用的网络环境,选择完后会重启APP生效"
        android:title="设置网络环境" />
</PreferenceScreen>

 

这里默认的值为1,也就是正式环境。现在关于xml就配置完了,该进入这个NetworkEnvironmentActivity里面去写代码了,首先继承AppCompatActivity,重写父类的onCreate方法,然后设置布局。现在看起来这个Activity就和常规的Activity差不多了。

package com.llw.network.environment;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.llw.network.R;

/**
 * 设置网络环境Activity
 * @author llw
 */
public class NetworkEnvironmentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_network_environment);
    }

}

 

当然这还是刚开始,下面一步一步完善这个Activity,首先增加两个成员变量。

	//网络环境
    public static final String NETWORK_ENVIRONMENT = "network_environment";
    //当前网络环境
    private static String mCurrentNetworkEnvironment = "";

 

下面会用到缓存,键就是NETWORK_ENVIRONMENT,常规这种键都是大写的。

 

先在NetworkEnvironmentActivity中创建一个内部类MyPreferenceFragment继承PreferenceFragmentCompat并实现Preference.OnPreferenceChangeListener。

	/**
     * 内部缓存变化监听类
     */
    public static class MyPreferenceFragment extends PreferenceFragmentCompat
            implements Preference.OnPreferenceChangeListener {

        //创建缓存
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            //这个相当于Activity的setContentView,从资源文件中添Preferences ,选择的值将会自动保存到SharePreferences
            addPreferencesFromResource(R.xml.environment_preference);
            //设置缓存变化监听 , 通过键来设置监听
            findPreference(NETWORK_ENVIRONMENT).setOnPreferenceChangeListener(this);
        }

        //缓存变化
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            if (!mCurrentNetworkEnvironment.equalsIgnoreCase(String.valueOf(newValue))) {
                //当前值与缓存中不一致时,说明切换了网络,这时提醒一下
                Toast.makeText(getContext(), R.string.network_change_tip, Toast.LENGTH_SHORT).show();
            }
            return true;
        }
    }

 

通过这个类,定义xml文件中,的操作方式,ListPreferenc这个控件中,默认是正式环境,当你修改之后,会将你修改的值存到缓存中,然后会进入这个缓存变化的回调中,此时提醒一下开发者,当然此时只是更换了缓存信息而已,此时应该退出当前应用,再重启,重启时读取缓存中的值,根据这个值去使用不同的环境,那么为了让这个过程显得不那么突兀,可以在页面返回的监听中做判断。

 

	/**
     * 页面返回
     */
    @Override
    public void onBackPressed() {
        //获取缓存对象
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        //通过键获取缓存则,没有则使用默认值
        String value = preferences.getString(NETWORK_ENVIRONMENT, "1");
        if (!mCurrentNetworkEnvironment.equalsIgnoreCase(value)) {
            //不一致.说明有修改,从操作系统中结束掉当前程序的进程
            android.os.Process.killProcess(android.os.Process.myPid());
        } else {
            //一致  没有修改则关闭当前页面
            finish();
        }
    }

onBackPressed可以监听页面的返回按钮的点击事件,我在这里判断是否有修改网络环境,因为缓存值修改就意味着网络环境修改,如果已经修改过则在返回页面时结束当前程序的进程,如果没有修改只是关闭当前的Activity而已。

 

而假如要在启动App时判断当前环境是否为正式环境时,还是需要去缓存来对比的,因此可以再写一个方法来判断当前是否为正式环境,方法如下:

 

	/**
     * 是否为正式环境
     */
    public static boolean isFormalEnvironment(Application application) {
        //获取当前应用的缓存
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
        String networkEnvironment = preferences.getString(NETWORK_ENVIRONMENT, "1");
        return "1".equalsIgnoreCase(networkEnvironment);
    }

因为当前只有正式和测试两种情况,因此可以用boolean就可以,多种情况你可以返回一个key的结果,每个key对应不同的网络,自己区分好就行。

 

最后在onCreate中配置Fragment的replace

	@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_network_environment);

        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content, new MyPreferenceFragment())
                .commit();
        //获取默认缓存
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        //如果没有值就默认为 “1”  在这里 1 表示正式环境
        mCurrentNetworkEnvironment = preferences.getString(NETWORK_ENVIRONMENT,"1");
    }

 

这样这个Activity就写完了,别忘了在AndroidManifest.xml中配置

 

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.llw.network">

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

    <application android:networkSecurityConfig="@xml/network_security_config">
        <activity
            android:name=".environment.NetworkEnvironmentActivity"
            android:label="@string/network_environment_setting"
            android:screenOrientation="portrait" />
    </application>

</manifest>

但是网络配置这一步还没有结束,之前在NetworkApi中配置了mBaseUrl这个成员变量,还记得吗?之前可是一直没有赋值的,我相信你已经猜到了,更改网络环境,实际上就是在更改mBaseUrl的值,只不过更改之前要根据缓存判断一下。

 

那么在NetworkApi中再增加一个成员变量

	//是否为正式环境
    private static boolean isFormal = true;

 

下面在NetworkApi中新增一个初始化的方法,代码如下:

 

	/**
     * 初始化
     */
	public static void init(INetworkRequiredInfo networkRequiredInfo) {
        iNetworkRequiredInfo = networkRequiredInfo;
        //当初始化这个NetworkApi时,会判断当前App的网络环境
        isFormal = NetworkEnvironmentActivity.isFormalEnvironment(networkRequiredInfo.getApplicationContext());
        if (isFormal) {
            //正式环境
            mBaseUrl = "https://gank.io";
        } else {
            //测试环境
            mBaseUrl = "https://cn.bing.com";
        }
    }

 

同样还要创建一个Service的实例方法,代码如下:

	/**
     * 创建serviceClass的实例
     */
    public static <T> T createService(Class<T> serviceClass) {
        return getRetrofit(serviceClass).create(serviceClass);
    }

OK,到目前为止,NetworkApi终于是写完了。

 

下面这个该进入使用环节了,下篇我们回到app模块使用网络框架。

 






 

————————————————
版权声明:本文为CSDN博主「初学者-Study」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38436214/article/details/111871786

分类
已于2021-3-3 09:56:38修改
收藏 1
回复
举报
回复
    相关推荐