動態接口實現網絡加載

1.要實現動態接口必須瞭解幾個定義:

  • 註解:
    定義註解(Annotation),也叫元數據。一種代碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,註釋。
    元註解:負責描述註解的註解
    1.@Target :標記註解用於描述什麼,可以使方法,屬性等等…
    2.@Retention:定義註解保留的時間
    3.@Documented:用於描述其它類型的annotation應該被作爲被標註的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。
    4.@Inherited:元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。

    1. 反射:通過.class類的描述類,直接生成對象,直接查找修改類的屬性,方法,靜態變量.

    2.動態接口

    目標:在通過網絡 訪問數據接口,並且對返回的json處理,添加在安卓控件過程中,封裝一個工具類,將需要傳遞的url寫在一個自定義的接口(內含一個傳參方法)裏傳入(通過註解傳入固定不變的部分,通過接口中某個方法傳遞進一個可變參數),通過工具類實例化接口,並在調用接口方法的時候執行代理invoke方法,實現網絡加載,具體代碼如下.

    1. 代理類:
public class Tools {
    public static<T> T getInstance(Class<T> type){
        Object o = Proxy.newProxyInstance(type.getClassLoader(), new Class[]{type}, new MyHandler());
        return ((T) o);
    }


    private static class MyHandler implements InvocationHandler{
        /**
         * invoke 方法在生成的接口對象調用其中方法的時候調用
         * @param proxy   代理:通過代理把下面方法加載進去
         * @param method   要加載的方法
         * @param args     要加載的方法的參數
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            UrlString annotation = method.getAnnotation(UrlString.class);
            if (annotation != null) {
                String url = String.format(Locale.CHINA, annotation.value(), args);
                Class<?> returnType = method.getReturnType();
                if (returnType.equals(DownWebTask.class)) {
                    ParameterizedType type = (ParameterizedType) method.getGenericReturnType();
                    Type entryType = type.getActualTypeArguments()[0];
                    return new DownWebTask<>(url, ((Class) entryType));
                }
            }
            return null;
        }
    }

}

2.網絡加載工具:

public class DownWebTask<T> extends AsyncTask<DownWebTask.Callback<T>,Void,Object> {
    private static final String TAG = DownWebTask.class.getSimpleName();
    //傳入參數     中間過程數據   返回值
    private String url;
    private Callback callback;
    private Class<T> t;
    public interface Callback<S>{
        void onSuccess(S t);
        void onFail(Exception e);
    }

    public DownWebTask(String url, Class<T> t) {
        this.url = url;
        this.t = t;
    }

    @Override
    protected Object doInBackground(Callback<T>... params) {
        callback=params[0];
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestMethod("GET");
            connection.setDoInput(true);
            int responseCode = connection.getResponseCode();
            if (responseCode==200){
                InputStream inputStream = connection.getInputStream();
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                int len;
                byte[] bytes = new byte[102400];
                while ((len=inputStream.read(bytes))!=-1){
                    byteArrayOutputStream.write(bytes, 0, len);
                }
                String s = byteArrayOutputStream.toString("UTF-8");
//                Log.d(TAG, "doInBackground: "+s);
                return new Gson().fromJson(s,t);
            }else {
                return new RuntimeException("網絡錯誤,responseCode "+responseCode);
            }
        } catch (IOException e) {
            return e;
        }
    }

    @Override
    protected void onPostExecute(Object o) {
        super.onPostExecute(o);
        if (t.isInstance(o)){
            callback.onSuccess(((T) o));
        }else if (o instanceof Exception){
            callback.onFail(((Exception) o));
        }
    }

}

3.自定義註解(用於修飾自己的接口)

//修飾註解的註解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UrlString {
    String value();
}

4.數據實體類

public class Entry {
    @SerializedName("message")
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

5.主程序

public class MainActivity extends AppCompatActivity implements DownWebTask.Callback<Entry>{

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text);
        Object instance = Tools.getInstance(DataInterface.class);
        ((DataInterface) instance).getShow(9987).execute(this);
    }


    @Override
    public void onSuccess(Entry t) {
        mTextView.setText(t.getMessage());
    }

    @Override
    public void onFail(Exception e) {
        Toast.makeText(MainActivity.this, "網絡異常", Toast.LENGTH_SHORT).show();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章