최상의 UI 업데이트 체계

5348 단어 개발 경험android
얼마 전에 Windows 데스크톱 프로그램에서 깨달은 이치를 썼다.
그렇습니다. 때때로 우리는 업무에 부합되는View를 만들거나 UI 대상이라고 부릅니다. 예를 들어 실시간 통신 소프트웨어의 친구 목록에 있는 모든 item을 만들어야 합니다. 그러면 이 item은 이미지, 이름, 세 가지 데이터 항목을 간단하게 설명해야 합니다.그러면 우리 이 View 대상은 세 가지 대응하는 방법으로 이 세 가지 속성을 설정해야 한다. 그리고 View가 나타날 때 우리의 최신 데이터를 표시하면 된다.
처음 시작할 때 나는 모두 꼿꼿이 이렇게 썼다.
//          ,    
class UserItemView extends View {
    ImageView mAvatar;
    TextView mName;
    TextView mDesc;
    
    public void setAvatar(Bitmap avatarImage) {
        mAvatar.setImage(avatarImage);
    }
    
    public void setName(String name) {
        mName.setText(name);
    }
    
    public void setDesc(String desc) {
        mDesc.setText(desc);
    }
}

처음엔 OK였어요. 완벽해 보였고 아무 문제 없었어요.만약 어떤 사용자의 데이터가 변했다면, 어떤 데이터를 업데이트했으면 좋겠다.
자, 이제 문제입니다. 이렇게 쓰는 문제는 상태/데이터 간의 상호 의존이 UI 디스플레이에 영향을 미칠 때 문제가 발생하고 코드가 혼란스러워진다는 것입니다.
설명 (desc) 이 비어 있으면 이미지를 표시하고, 비어 있지 않으면 이미지를 표시하지 않습니다.수요는 확실히 이상하지만, 실제 업무에서는 반드시 유사한 상황을 만날 것이다.
그럼 우선 코드를 당연하게 바꾸려고 합니다.
class UserItemView extends View {
    ImageView mAvatar;
    TextView mName;
    TextView mDesc;
    
    String mDescData;
    
    public void setAvatar(Bitmap avatarImage) {
        mAvatar.setImage(avatarImage);
    }
    
    public void setName(String name) {
        mName.setText(name);
    }
    
    public void setDesc(String desc) {
        mDescData = desc;
        if (mDescData == null || mDescData .equals("")) {
            mAvatar.setVisible(true);
        } else {
            mAvatar.setVisible(false);
        }
        mDesc.setText(mDescData );
    }
}

봐라, 지금 묘사한 방법에서 프로필 사진의 표시 상황을 관리해야 하니, 이것은 매우 구역질이 난다.만약 더 많은 데이터 항목과 상태, 더 많은 UI 컨트롤러가 있다면 그들 사이에는 매우 많은 의존 관계가 있을 것이다. 이런 식으로 쓰면 모든 방법의 논리가 매우 징그럽고 복잡해질 것이다.심지어 어떤 UI의 상태를 설정하려면 다른 데이터 항목에 의존해야 하기 때문에 어쩔 수 없이 무관한 데이터를 매개 변수로 전송하면 이렇게 된다.
// !!!  !!!             !!!
public void setAvatar(Bitmap avatarImage, String desc) {
    mAvatar.setImage(avatarImage);
    if (desc== null || desc.equals("")) {
        mAvatar.setVisible(true);
    } else {
        mAvatar.setVisible(false);
    }
}

당시에 나의 UI는 이미 매우 메스꺼워졌다. 이런 상황에서 나는 UI 대상에 대한 업데이트는 그 자리에서 할 수 없다는 것을 깨달았다. UI 대상의 업데이트는 하나의 통일된 방법으로 해야 하고 UI 디스플레이 상황을 바꾸는 setXXXX 방법은 두 가지만 해야 한다. 하나는 데이터를 이 대상의 구성원 속성에 설정하는 것이다.다른 하나는 UI를 업데이트하기 위해 UI를 통합하는 방법입니다.
사실 하나의 표준적인 디자인이 눈앞에 있었는데, 그 순간에 이르러서야 나는 비로소 진정한 이해를 깨달았다.바로 안드로이드View입니다.안드로이드의 각 View의 하위 클래스는 매우 많은 set 방법이 있다. 예를 들어 TextView,setText,setTextColor 등이 있다.그것은 모든 set 방법으로 사실상 이 대상에게 데이터의 변화를 주고 상관하지 않는다.시스템이 OnDraw 메서드를 호출할 때까지 기다렸다가 OnDraw 메서드에서 UI를 통일적으로 업데이트합니다.
다음은 간단해.우리의 코드는 이렇게 바뀌었다.
class UserItemView extends View {
    ImageView mAvatar;
    TextView mName;
    TextView mDesc;
    
    String mNameData;
    String mDescData;
    Bitmap mAvatarData;
    
    public void updateView() {
        mAvatar.setImage(mAvatarData);
        if (mDescData== null || mDescData.equals("")) {
            mAvatar.setVisible(true);
        } else {
            mAvatar.setVisible(false);
        }
        
        mDesc.setText(mDescData);
        
        mName.setText(mNameData);
    }
    
    public void setAvatar(Bitmap avatarImage) {
        mAvatarData = avatarImage;
        updateView();
    }
    
    public void setName(String name) {
        mNameData = name;
        updateView();
    }
    
    public void setDesc(String desc) {
        mDescData = desc;
        updateView();
    }
}

주의해야 할 것은 updateView 방법이 추가되었다. 이 방법은 데이터를 UI에 업데이트하는 데 사용된다. 이렇게 쓰고 다른 set 방법은 일률적으로 데이터를 저장하는 일만 한다. updateView 방법은 현재의 데이터 상태에 따라 UI를 업데이트한다. 이렇게 하면 set 방법은 깨끗하고 깔끔해진다.논리가 아무리 복잡한 디스플레이 논리라도 두려워하지 말고 updateView에서 하면 된다.
내가 일찍이 유지하고 있던 Activity는 대략 15+개의View, 20-30개의 데이터와 상태가 있는데 이런 데이터와 상태는 수수께끼처럼 이view의 디스플레이를 기억한다.당시에는 젊고 철이 없어서 데이터 변화의 뒤(다음 줄)에 꼿꼿이 서서 바로 UI의 상태를 업데이트했다.이러한 위치는 다음과 같습니다.
  • 클릭 이벤트
  • 시스템 콜백
  • 네트워크 리콜 요청
  • 타이머,handler
  • 이렇게 많은 곳에서 데이터를 업데이트하고 UI를 바꾸니 유지하기에는 정말 똥이다.
    나중에 제가 위의 기교를 깨달은 후에 저는 한 라운드를 재구성했습니다. 그 안에 아주 큰 업데이트 뷰 방법이 있고 모든 뷰를 업데이트했습니다.
    여기에 또 다른 작은 기교가 있다. 바로 당신이 1w개의 View와 1w개의 상태를 가지고 있는지, 상태에 따라 분류해서 쓰든지, 아니면 View에 따라 분류해서 쓰든지.이 뜻은 정상인으로 생각하라. 예를 들어 너의 페이지에는 두 가지 모델이 있는데 일반인은 쓸 줄 안다.
    if (mode == A) {
        viewA.xxxxxx
        viewB.xxxxxx
        ...
    } else if (mode == B) {
        viewA.xxxxxx
        viewB.xxxxxx
        ...
    }

    이렇게 쓰다가 또 문제가 생겼어, 소년, 너의 상태가 두 가지밖에 없다고 생각하니?모든 UI 객체가 하나의 상태에만 의존한다고 생각합니까?이렇게 우아하게 if와 else에 딱 분포되나요?네가 틀렸어, 이걸 필요로 하는 건 아주 징그럽고 논리에 전혀 맞지 않아.
    이렇게 쓰면, 상태가 매우 많을 때, 이view의 업데이트를 어디에 두어야 할지, 새로 추가된 상태가 있으면 또 영향을 끼치기 어렵다.이전의 논리에 영향을 주지 않기 위해서, 너는 왕왕 뒤에 한 줄을 더해서, 이렇게 많아도 유지하기 어렵다.
    그럼 어떻게 해요?가장 간단합니다. View별로 분류해서 쓰십시오.너는 1w개의 뷰가 있겠지, 그럼 한 명씩 와서 첫 번째 뷰를 먼저 처리해라. 첫 번째 뷰는 어떤 영향을 받니?모두 써라.if-else도 좋고, 무엇이든지 좋다. 어쨌든 처음에 이 몇 줄의 코드는 먼저 View1을 해결해라.
    그리고 다시 한 번 View2, View3의 논리를 쓰세요. 유일한 단점은 당신의 판단을 반복해서 써야 한다는 것입니다.거추장스러워 보입니다.view1과view2는 그들의 디스플레이 논리가 같을 가능성이 높습니다. 당신은 그들을if-else에 매우 쓰고 싶지만, 나는 당신이 이렇게 하지 말라고 건의합니다. 가장 높은 변통성을 위해서 그들을 분리해서 쓰십시오.
    네가 나중에 유지할 때, 어느 뷰에 문제가 생겼는지, 너는 그 덩어리만 찾으면 돼. 다른 것은 상관할 필요가 없어.
    모두들 즐겁게 일하세요!

    좋은 웹페이지 즐겨찾기