com.taobao.weex.ui.component.list.template.CellDataManager.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.weex.ui.component.list.template.CellDataManager.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.taobao.weex.ui.component.list.template;

import android.support.v4.util.ArrayMap;
import android.text.TextUtils;

import com.alibaba.fastjson.JSONArray;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.bridge.WXBridgeManager;
import com.taobao.weex.utils.WXUtils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by furture on 2018/1/23.
 * template data manager, manage data and render state
 */
public class CellDataManager {

    private static final String VIRTUAL_COMPONENT_SEPRATOR = "@";

    public static final String SUB_COMPONENT_TEMPLATE_ID = "@templateId";

    public static final String VIRTUAL_COMPONENT_ID = "@virtualComponentId";

    /**
     * template list data, update should vis data manager interface, this field is read only
     * */
    JSONArray listData;

    /**
     * current template list
     * */
    public final WXRecyclerTemplateList templateList;

    /**
     * data render state for position, itemId?dirty?and other info
     * */
    private Map<Integer, CellRenderState> renderStates = new ArrayMap<>();

    /**
     * list virtual component data, rendet state
     * key virtual component id, value is cell render state.
     * */
    private Map<String, CellRenderState> virtualComponentRenderStates;

    /**
     * template list data manager
     * */
    public CellDataManager(WXRecyclerTemplateList templateList) {
        this.templateList = templateList;
    }

    /**
     * get current render state for current position, never return null.
     * */
    public CellRenderState getRenderState(int position) {
        CellRenderState renderState = renderStates.get(position);
        if (renderState == null) {
            renderState = new CellRenderState();
            renderState.position = position;
            renderStates.put(position, renderState);
        }
        if (position != renderState.position) {
            renderState.position = position;
            renderState.hasPositionChange = true;
        }
        return renderState;
    }

    /**
     * @param  virutalComponentId virutalComponentId
     * @param  data   update    virutalComponent's data
     * update virtual component data
     * */
    public void updateVirtualComponentData(String virutalComponentId, Object data) {
        if (virtualComponentRenderStates != null) {
            CellRenderState cellRenderState = virtualComponentRenderStates.get(virutalComponentId);
            if (cellRenderState != null) {
                cellRenderState.getVirtualComponentDatas().put(virutalComponentId, data);
                cellRenderState.hasVirtualCompoentUpdate = true;
            } else {
                if (WXEnvironment.isApkDebugable()) {
                    throw new IllegalArgumentException(
                            "virtualComponentDatas illegal state empty render state" + virutalComponentId);
                }
            }
        } else {
            if (WXEnvironment.isApkDebugable()) {
                throw new IllegalArgumentException("virtualComponentDatas illegal state " + virutalComponentId);
            }
        }
    }

    /**
     * @param  position  current position virtual component
     * @param  virutalComponentId virutalComponentId
     * @param  data   update    virutalComponent's data
     * create virtual component data
     * */
    public void createVirtualComponentData(int position, String virutalComponentId, Object data) {
        if (virtualComponentRenderStates == null) {
            virtualComponentRenderStates = new HashMap<>(8);
        }
        CellRenderState renderState = renderStates.get(position);
        renderState.getVirtualComponentDatas().put(virutalComponentId, data);
        virtualComponentRenderStates.put(virutalComponentId, renderState);

    }

    /**
     * @param  listData setList data
     * clear render state for current cell, and virtual component data
     * */
    public void setListData(JSONArray listData) {
        if (this.listData != listData) {
            if (this.listData != null) {
                if (WXUtils.getBoolean(templateList.getAttrs().get("exitDetach"), true)) {
                    for (int i = 0; i < this.listData.size(); i++) {
                        cleanRenderState(renderStates.remove(i));
                    }
                }
            }
            this.listData = listData;
            renderStates.clear();
            if (virtualComponentRenderStates != null) {
                virtualComponentRenderStates.clear();
            }
        }
    }

    /**
     * @param index insert index
     * @param  data  data object
     * insert data at current index
     * */
    public boolean insertData(int index, Object data) {
        listData.add(index, data);
        boolean renderStateChange = false;
        for (int i = listData.size(); i >= index; i--) {
            CellRenderState state = renderStates.remove(i);
            if (state != null) {
                renderStates.put(i + 1, state);
                renderStateChange = true;
            }
        }
        return renderStateChange;
    }

    /**
     *
     * @param index insert index
     * @param  data  data object
     * insert data at current index
     * */
    public boolean insertRange(int index, JSONArray data) {
        listData.addAll(index, data);
        boolean renderStateChange = false;
        for (int i = listData.size() - 1; i >= index; i--) {
            CellRenderState state = renderStates.remove(i);
            if (state != null) {
                renderStates.put(i + 1, state);
                renderStateChange = true;
            }
        }
        return renderStateChange;
    }

    /**
     * @param  data  data object
     * @param index insert index
     * update data, reset new render state,
     * return true if only data changed, false if viewType changed
     * */
    public boolean updateData(Object data, int index) {
        boolean onlyDataChange = TextUtils.equals(templateList.getTemplateKey(index),
                templateList.getTemplateKey(data));
        listData.set(index, data);
        if (!onlyDataChange) {
            //structure changed, reset render state
            cleanRenderState(renderStates.remove(index));
        } else {
            CellRenderState renderState = renderStates.get(index);
            if (renderState != null) {
                renderState.hasDataUpdate = true;
            }
        }
        return onlyDataChange;
    }

    /**
     * @param index
     * remove data, and its render state  and  virtual's data
     * */
    public void removeData(Integer index) {
        listData.remove((int) index); //remove by index
        cleanRenderState(renderStates.remove(index));
        int count = listData.size() + 1;
        for (int i = index + 1; i < count; i++) {
            CellRenderState state = renderStates.remove(i);
            if (state != null) {
                renderStates.put(i - 1, state);
            }
        }
    }

    /**
     *  clean render state, if has virtual component, call virtual component detach lifecycle
     * */
    private void cleanRenderState(CellRenderState renderState) {
        if (renderState == null) {
            return;
        }
        if (renderState.hasVirtualComponents()) {
            Collection<String> virtualComponentIds = renderState.getVirtualComponentIds().values();
            for (String virtualComponentId : virtualComponentIds) {
                if (virtualComponentRenderStates != null) {
                    virtualComponentRenderStates.remove(virtualComponentId);
                }
                WXBridgeManager.getInstance().asyncCallJSEventVoidResult(WXBridgeManager.METHD_COMPONENT_HOOK_SYNC,
                        templateList.getInstanceId(), null, virtualComponentId, VirtualComponentLifecycle.LIFECYCLE,
                        VirtualComponentLifecycle.DETACH, null);

            }
        }
    }

    /**
     * create virtualComponentId
     * */
    public static String createVirtualComponentId(String listRef, String viewTreeKey, long itemId) {
        return listRef + VIRTUAL_COMPONENT_SEPRATOR + viewTreeKey + VIRTUAL_COMPONENT_SEPRATOR + itemId;
    }

    /**
     * get list ref from virtualComponentId
     * */
    public static String getListRef(String virtualComponentId) {
        if (virtualComponentId == null) {
            return null;
        }
        return virtualComponentId.split(VIRTUAL_COMPONENT_SEPRATOR)[0];
    }

}