2013-08-03 17 views
0

我正在編寫一個類似AQuery的庫,但它具有操作元素的精煉語法。更好的方式來使用空檢查,類型鑄造價值?

本質上,AQuery所做的就是安全地訪問視圖層次結構,並允許您在ImageView和TextView等對象上調用子類方法。

我已經寫了通過使用下面的代碼使用View的子類的一般方法:

Query對象是所使用操作視圖層次結構的基本對象。基本格式如下所示:

public class Query { 
    private View mView; 
    // ... 
} 

接下來是通用接口。這是查詢對象的內部接口:

private interface Operation<T extends View> { 
    public void execute(T view); 
} 

接着是Queryrun方法。這將檢查該查詢表示當前節點,並調用操作對象的execute方法,如果它是成功的:

private <T extends View> Query run(Class<T> cls, Operation<T> operation) { 
    T t = cls.cast(mView); 

    if (t == null) { 
     Log.e(TAG, "view is not a " + cls.getSimpleName()); 
    } else { 
     operation.execute(t); 
    } 

    return this; 
} 

所以現在模板代碼寫的是我用類似這樣的方法來實現功能:

public Query text(final CharSequence str) { 
    return run(TextView.class, new Operation<TextView>() { 

     @Override 
     public void execute(TextView view) { 
      view.setText(str); 
     } 
    }); 
} 

對於修改View層次結構的每個方法,我都必須編寫這個樣板文件代碼。

有什麼辦法可以重構此代碼,使像text這樣的方法更簡單嗎?

回答

2

僅供參考你在這裏沒有真正檢查mView的類型。如果mView不能分配給類型T,Class.cast將拋出一個ClassCastException,因此那裏的日誌消息並不真正表示發生了什麼。當且僅當mView爲空時,t == null纔會成立。

如果沒有Query的某些存根,你會很難分辨出你想要達到的目標。如果您的使用允許查詢的參數化,那麼您可以將操作作爲其功能。這將爲您提供與查詢類型匹配的視圖的編譯時檢查。例如

public interface Query<ViewT extends View> { 
    void run(ViewT view); 
} 

public Query<TextView> text(final CharSequence str) { 
    return new Query<TextView>() { 
     public void run(TextView view) { 
      view.setText(str); 
     } 
    }; 
} 

如果這是不可能的(即視圖類型從在編譯時已知),那麼你仍然可以參數執行它,只是,當且僅當參數類型的查詢類型匹配執行的操作。例如:

public interface Query { 
    void run(View view); 
} 

private abstract class TypedQuery<ViewT extends View> implements Query { 
    private final Class<ViewT> viewType; 

    private TypedQuery(Class<ViewT> viewType) { 
     this.viewType = viewType; 
    } 

    public final void run(View view) { 
     if (viewType.isInstance(view)) { 
      runInternal((ViewT) view); 
     } else { 
      Log.e(TAG, "view " + view + " is not a " + viewType.getSimpleName()); 
     } 
    } 

    protected abstract void runInternal(ViewT view); 
} 

public Query text(final CharSequence str) { 
    return new TypedQuery<TextView>(TextView.class) { 
     @Override 
     protected void runInternal(TextView view) { 
      view.setText(str); 
     } 
    }; 
} 
+0

感謝您的回答,它允許我把我的頭放在不同的空間。 :d – Brad