1. 程式人生 > >JavaFX8 -- TableView中TableCell物件管理的奇怪問題-多次非同步重新整理單元格慎重!

JavaFX8 -- TableView中TableCell物件管理的奇怪問題-多次非同步重新整理單元格慎重!

早前,我在JavaFX2(JDK 7)中自定義了一個TextFieldTableCell,對TextField實現了一些特定的事件監聽以及觸發TableView再次重新整理等,以下是簡單的程式碼

import javafx.application.Platform;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;

public class TextfieldTableCell extends TableCell<MyTableData, String> {

    public TextfieldTableCell() {
    }

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        updateGraphic();
    }

    private void updateGraphic() {
        setText(null);
        setGraphic(null);

        final int index = getIndex();
        if (isEmpty() || index < 0) {
        } else {
            final TextField textField = new TextField();

            textField.textProperty().addListener(new ChangeListener<String>() {

                @Override
                public void changed(ObservableValue<? extends String> ov, String t, String t1){
		    //ignore some action handler
                }             
	    });

            //Forget why use asynchronous flush
            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    setGraphic(textField);
                }
            });
        }
    }
}

問題在於,這段程式碼在Java 7中可以正確執行,在Java8中則有顯示異常,會導致第一個空白行(行號2)重複顯示最後一個數據行(行號1)的內容。


經過除錯仔細分析其中可能的原因,終於找到問題所在:

JavaFX8中每個單元格都會對應一個獨立TextFieldTableCell物件,但是並不是每次重新整理都重新初始化一個新的物件,而是會優先使用已經存在的物件(也許是為了效能和記憶體優化),可嚴重的問題在於對於同一行號,並不保證每次拿到的都是同一個物件。

注:這個結論還沒有尋求官方資料的理論支援,而是自己總結的

由於我使用了非同步重新整理,而且每個單元格重新整理可能觸發多次,就導致了本來要重新整理行1,卻重新整理了行2情況(因為行2使用了行1的TextFieldTableCell物件)

。於是在非同步重新整理時,我需要增加行號的判斷即可:

            Platform.runLater(new Runnable() {

                @Override
                public void run() {
                    if (getIndex() == index) {//Important(Add in JDK 8)
                        setGraphic(textField);
                    }
                }
            });


不過也許一個單元格觸發多次重新整理本來就不合理...