2013-08-03 1 views
0

Я пишу библиотеку, похожую на AQuery, но с уточненным синтаксисом для управления элементами.Лучший способ использовать значение null checked, type casted value?

По существу, что AQuery обеспечивает безопасный доступ к иерархии представлений и позволяет вызывать методы подкласса на таких объектах, как ImageView и TextView.

Я написал общий способ использовать подкласс View, используя следующий код:

Моего Query объекта является базовым объектом, который используется для управления иерархией просмотра. Основной формат выглядит следующим образом:

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

Далее приведен общий интерфейс. Это внутренний интерфейс объекта запроса:

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

Далее идет run метод Query. Это проверяет текущий узел представляет этот запрос и вызывает 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); 
     } 
    }); 
} 

Для каждого метода, который изменяет иерархию вида, я должен написать этот шаблонный код.

Есть ли способ, который я могу реорганизовать этот код, чтобы методы, подобные text проще?

ответ

2

FYI, что у вас здесь, на самом деле не проверяет тип mView. Class.cast будет генерировать ClassCastException, если mView не может быть присвоен типу T, поэтому сообщение журнала там фактически не представляет, что происходит. t == null будет истинным тогда и только тогда, когда mView будет 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

Смежные вопросы