Android - 动态视图时序问题?

时间:2015-05-29 23:25:00

标签: java android dynamic views timing

我是一名Android新手开发者,我正在开发一个小型Android应用程序的问题,我怀疑这与动态视图创建的时间有关。它是一个小记分员应用程序,它具有动态生成的播放器按钮和文本字段,在Player类中定义。以下是我如何做到这一点的摘录:

    public Player(String name, int score, int number, boolean enabled, RelativeLayout mainScreen, List<Button> presetButtonList, Editor editor, Context context) {
            super();
            this.name = name;
            this.score = score;
            this.number = number;
            this.enabled = enabled;
            this.editor = editor;

            // Get the lowest child on the mainScreen
            Integer count = mainScreen.getChildCount(), lowestChildId = null;
            Float lowestChildBottom = null;
            for (int i = 0; i < count; i++) {
                View child = mainScreen.getChildAt(i);
                if ((lowestChildId == null  || child.getY() > lowestChildBottom) && 
                        !presetButtonList.contains(child)) {
                    lowestChildId = child.getId();
                    lowestChildBottom = child.getY();
                }
            }

            playerNameText = (EditText) setTextViewDefaults(new EditText(context), name);
            playerNameText.setSingleLine();
    //      playerNameText.setMaxWidth(mainScreen.getWidth());
    //      playerNameText.setEllipsize(TextUtils.TruncateAt.END);  //TODO: Prevent names which are too long for screen
            playerNameText.addTextChangedListener(new TextWatcher() {

                  public void afterTextChanged(Editable changedText) {
                      setName(changedText.toString());
                      updateScreen();
                  }

                  public void beforeTextChanged(CharSequence changedText, int start, int count, int after) {}

                  public void onTextChanged(CharSequence changedText, int start, int before, int count) {}
               });
            RLParams = new RelativeLayout.LayoutParams(
                    RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
            if (lowestChildId != null) {
                RLParams.addRule(RelativeLayout.BELOW, lowestChildId);
            } else {
                RLParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                RLParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
            }
            RLParams.setMargins(0, 10, 0, 10);      
            mainScreen.addView(playerNameText, RLParams);

该类以类似的方式进一步定义按钮等,将顶部与名称文本视图对齐。当用户点击按钮添加播放器时我会调用它,并且它可以正常工作,在屏幕下方显示第一个播放器下面的每个播放器。当我在开始时加载一堆已保存的玩家时会出现问题。这是我加载球员的地方:

public void loadData() {
        RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
        playerCount = savedData.getInt("playerCount", playerCount);
        Player player;
        String name;
        playerList.clear();
        for (int i=1; i<=playerCount; i++) {
            name = savedData.getString("name" + i, null);
            if (name != null) {
                Log.v("name", name);
                player = new Player(name, savedData.getInt("score" + i, 0), i, savedData.getBoolean("enabled" + i, false), mainScreen, presetButtonList, editor, this);             
                playerList.add(player);
                player.updateScreen();
            }
        }
        updateScreen();
    }

最后,我在应用程序启动时调用loadData()方法,这里:

@Override
protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    savedData = this.getPreferences(Context.MODE_PRIVATE);
    editor = savedData.edit();

    presetButtonList.add((Button)findViewById(R.id.newGame));
    presetButtonList.add((Button)findViewById(R.id.addPlayer));
    presetButtonList.add((Button)findViewById(R.id.removePlayer));

    loadData();     
}

结果呢?当有两个以上的玩家加载时,所有玩家都会被加载到玩家2之上的同一个位置。

我怀疑某些球员都是在同一时间生成的,因此所有人都认为最低的玩家视图是玩家1,而不是互相检查。我试过比onCreate()更晚地触发加载,但它仍然会发生。我还尝试在每个玩家加载之后在loadData()的for循环中添加3秒睡眠以查看是否有帮助,但没有运气。

我做出错误的假设吗?我做错了什么,我该如何解决?

2 个答案:

答案 0 :(得分:0)

我怀疑这里发生的事情是您尝试定位没有ID的视图(看起来您没有在代码中的任何位置设置它们)。动态创建的视图不会自动拥有ID,因此对getId()的调用将返回NO_IDSee documentation)。如果您想使用ID,则必须使用View.setId()自行设置。

答案 1 :(得分:0)

毕竟这是个时间问题。我需要等待主屏幕加载才能添加视图。不幸的是,在UI线程上的所有活动都完成之前,它永远不会加载。

因此,我需要线程化。我最终将loadData()放在一个线程中,如下所示:

new Thread(new loadDataAsync(this)).start();



class loadDataAsync implements Runnable {

    MainActivity mainActivity;

    public loadDataAsync(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(700);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        loadData(mainActivity);         
    }
}

然后我在初始睡眠后在UI线程上创建了播放器,以便为UI加载时间。

runOnUiThread(new Runnable() {
                Player player;
                RelativeLayout mainScreen = (RelativeLayout)findViewById(R.id.relativeLayout);
                @Override
                public void run() {
                    player = new Player(savedData.getString("name" + playerNum, null), savedData.getInt("score" + playerNum, 0), playerNum, savedData.getBoolean("enabled" + playerNum, false), mainScreen, presetButtonList, editor, mainActivity);    
                    playerList.add(player);
                    player.updateScreen();
                    mainScreen.invalidate();
                }
            });

不是最优雅的解决方案,但现在可以使用。

相关问题