Child Window of TableView Slow to update

You must Login before you can answer or comment on any questions.

I have a tableview populated by remote data and clicking the row opens a details window. Each time I navigate back to the table and select a different row when the detail window opens there is a slight delay where you can see the old content being replaced by the new content, rather than it just being there.

There is no delay on the simulator, just when it's loaded on the device.

Also just in case it's of relevance the tableview is on a tab.

function eventsWindow() {
 
    //declare module dependencies
    var MasterView = require('ui/common/EventsMasterView'),
        DetailView = require('ui/common/EventsDetailView');
 
    //create object instance
    var self = Ti.UI.createWindow({
        backgroundColor:'#f1f1f1',
        navBarHidden:true
    });
 
    //construct UI
    var masterView = new MasterView(),
        detailView = new DetailView();
 
    //create master view container
    var masterContainerWindow = Ti.UI.createWindow({
        title:'Events',
        barColor : '#C23A25'
    });
    masterContainerWindow.add(masterView);
 
    //create detail view container
    var detailContainerWindow = Ti.UI.createWindow({
        barColor : '#C23A25',
        tabBarHidden : true
    });
    detailContainerWindow.add(detailView);
 
    //create iOS specific NavGroup UI
    var navGroup = Ti.UI.iPhone.createNavigationGroup({
        window:masterContainerWindow
    });
    self.add(navGroup);
 
    //add behavior for master view
    masterView.addEventListener('itemSelected', function(e) {
        detailView.fireEvent('itemSelected',e);
        navGroup.open(detailContainerWindow);
    });
 
    return self;
};
 
module.exports = eventsWindow;
If stripped a bit out of this code, I don't think it will be relevant anyway it just the code I use to get the remote data.
function MasterView() {
    var self = Ti.UI.createView({
        backgroundColor : 'white'
    });
 
    var DrupaniumEvents = require('/drupanium_framework/drupanium_events');
 
    DrupaniumEvents.drupaniumGetEvents(DrupaniumApp.getDrupaniumURLS('rest_path'), DrupaniumApp.getDrupaniumURLS('site_path'), 5000, function(data) {
        if (data) {
            var rowData = [];
            for (var i = 0; i < data.length; i++) {
 
                var events_view = Titanium.UI.createView({
                    height : Ti.UI.SIZE,
                    top : 5,
                    left : 5,
                    bottom : 5
                });
 
                var events_image = Titanium.UI.createImageView({
                    image : DrupaniumEvents.getDrupaniumEVENTS('eventsImage'), // the image for the image view
                    width : 48,
                    height : 48,
                    left : 0,
                    hires : true
                });
                events_view.add(events_image);
 
                var events_large_image = Titanium.UI.createImageView({
                    image : DrupaniumEvents.getDrupaniumEVENTS('eventsLargeImage'), // the image for the image view
                    width : 48,
                    height : 48,
                    left : 0,
                    hires : true
                });
 
                var eventsDateLabel = Ti.UI.createLabel({
                    height : Ti.UI.SIZE,
                    color : '#444444',
                    text : DrupaniumEvents.getDrupaniumEVENTS('eventsDate'),
                    top : 0,
                    left : 55,
                    font : {
                        fontSize : 12
                    }
                });
                events_view.add(eventsDateLabel);
 
                var eventsTitleLabel = Ti.UI.createLabel({
                    height : Ti.UI.SIZE,
                    color : '#444444',
                    text : DrupaniumEvents.getDrupaniumEVENTS('eventsTitle'),
                    top : 15,
                    left : 55,
                    font : {
                        fontSize : 18,
                        fontFamily : "League Gothic"
                    }
                });
                events_view.add(eventsTitleLabel);
 
                var eventsSubTitleLabel = Ti.UI.createLabel({
                    text : DrupaniumEvents.getDrupaniumEVENTS('eventsSubTitle')
                });
 
                var eventsDescriptionLabel = Ti.UI.createLabel({
                    text : DrupaniumEvents.getDrupaniumEVENTS('eventsDescription')
                });
 
                var eventsInfoLabel = Ti.UI.createLabel({
                    text : DrupaniumEvents.getDrupaniumEVENTS('eventsInfo')
                });
 
                var row = Titanium.UI.createTableViewRow({
                    backgroundColor : 'transparent',
                    height : Ti.UI.SIZE,
                    hasChild : true,
                });
                row.eventsDateLabel = eventsDateLabel;
                row.eventsTitleLabel = eventsTitleLabel;
                row.eventsSubTitleLabel = eventsSubTitleLabel;
                row.eventsDescriptionLabel = eventsDescriptionLabel;
                row.eventsInfoLabel = eventsInfoLabel;
                row.events_large_image = events_large_image;
                row.add(events_view);
                row.video = DrupaniumEvents.getDrupaniumEVENTS('eventsVideo');
                rowData[i] = row;
            }
 
            var tableView = Titanium.UI.createTableView({
                data : rowData,
                separatorColor : '#F1F1F1'
            });
 
            self.add(tableView);
 
            tableView.addEventListener('click', function(e) {
                self.fireEvent('itemSelected', {
                    date : e.rowData.eventsDateLabel.text,
                    title : e.rowData.eventsTitleLabel.text,
                    sub_title : e.rowData.eventsSubTitleLabel.text,
                    description : e.rowData.eventsDescriptionLabel.text,
                    info : e.rowData.eventsInfoLabel.text,
                    image : e.rowData.events_large_image.image,
                    video : e.rowData.video,
                });
            });
 
        } else {
 
        }
    });
    return self;
}
 
module.exports = MasterView;
function DetailView() {
    var self = Ti.UI.createScrollView({
        contentHeight : 'auto',
    });
 
    var container = Ti.UI.createView({
        height : Ti.UI.SIZE,
        layout : 'vertical',
        backgroundColor : '#ffffff',
        borderColor : '#cccccc',
        borderWidth : 1,
        borderRadius : 2,
        left : 5,
        top : 5,
        right : 5,
        bottom : 5,
        shadow : {
            color : '#000',
            offset : {
                x : 0,
                y : 1
            },
            opacity : 0.4,
            blur : 2
        }
    });
 
    var header = Ti.UI.createView({
        backgroundColor : '#f8f8f8',
        layout : 'vertical',
        height : Ti.UI.SIZE
    });
 
    var image = Titanium.UI.createImageView({
        image : '', // the image for the image view
        width : 80,
        height : 80,
        hires : true,
        borderColor : '#f1f1f1',
        borderWidth : 1,
        left : 10,
        top : 10,
        bottom : 10
    });
    header.add(image);
 
    var date = Ti.UI.createLabel({
        text : 'Please select an item',
        height : 'auto',
        width : 'auto',
        color : '#444',
        left : 95,
        top : -85,
        right : 10,
        font : {
            fontSize : 12,
            fontFamily : "Helvetica Neue"
        },
        shadowColor : '#fff',
        shadowOffset : {
            x : 1,
            y : 1
        }
    });
    header.add(date);
 
    var title = Ti.UI.createLabel({
        text : 'Please select an item',
        height : 'auto',
        width : 'auto',
        color : '#444',
        left : 95,
        right : 10,
        font : {
            fontSize : 21,
            fontFamily : "League Gothic"
        },
        shadowColor : '#fff',
        shadowOffset : {
            x : 1,
            y : 1
        }
    });
    header.add(title);
 
    var sub_title = Ti.UI.createLabel({
        text : 'Please select an item',
        height : 'auto',
        width : 'auto',
        color : '#444',
        left : 95,
        right : 10,
        bottom : 10,
        font : {
            fontSize : 12,
            fontFamily : "Helvetica Neue"
        },
        shadowColor : '#fff',
        shadowOffset : {
            x : 1,
            y : 1
        }
    });
    header.add(sub_title);
 
    container.add(header);
 
    var line1 = Ti.UI.createView({
        top : 0,
        height : 1,
        backgroundColor : '#f1f1f1',
    });
 
    container.add(line1);
 
    var event_info = Ti.UI.createView({
        layout : 'vertical',
        height : Ti.UI.SIZE
    });
 
    var info = Ti.UI.createLabel({
        text : 'Please select an item',
        height : 'auto',
        width : 'auto',
        color : '#444',
        left : 10,
        right : 10,
        top : 5,
        bottom : 5,
        font : {
            fontSize : 12,
            fontFamily : "Helvetica Neue"
        }
    });
 
    event_info.add(info);
 
    container.add(event_info);
 
    var content = Ti.UI.createView({
        layout : 'vertical',
        height : Ti.UI.SIZE,
        left : 10,
        right : 10,
        bottom : 10,
        top : 10
    });
 
    var description = Ti.UI.createLabel({
        text : 'Please select an item',
        height : 'auto',
        width : 'auto',
        color : '#444',
        font : {
            fontSize : 14
        }
    });
    content.add(description);
 
    container.add(content);
 
    var line2 = Ti.UI.createView({
        top : 0,
        height : 1,
        backgroundColor : '#f1f1f1',
    });
 
    container.add(line2);
 
    var footer = Ti.UI.createView({
        backgroundColor : '#f8f8f8',
        layout : 'vertical',
        height : 34
    });
 
    var video_url;
 
    var video = Ti.UI.createButton({
        backgroundImage : 'images/icons/video-icon.png',
        width : 24,
        height : 24,
        right : 10,
        top : 5,
        bottom : 5
    });
    footer.add(video);
 
    container.add(footer);
 
    self.add(container);
 
    self.addEventListener('itemSelected', function(e) {
        date.text = e.date;
        title.text = e.title;
        sub_title.text = e.sub_title;
        image.image = e.image;
        description.text = e.description;
        info.text = e.info;
        video_url = e.video;
    });
 
    return self;
};
 
module.exports = DetailView;

2 Answers

First off, big points for the CommonJS modules! :-)

Are you building for iOS and android? If you're building for android, I would recommend that you don't reuse the detailcontainerwindow and the detailview the way you are. My first inclination was to try to do that to save resources. It was horribly unstable on android. And frankly, the creation of the window and its child views doesn't seem to be a huge deal from a performance or memory usage standpoint, at least in my app.

So if you create the detail view from scratch, it may sidestep the issues you're seeing where you can see the old content momentarily.

— answered 12 months ago by Jason Priebe
answer permalink
1 Comment
  • This is just on ios at the moment, not got onto doing the android version yet and still trying to get my head round CommonJS modules. Does your answer still apply to ios?

    — commented 12 months ago by Marcus Williams

This is just on ios at the moment, not got onto doing the android version yet and still trying to get my head round CommonJS modules.

Does your answer still apply to ios?

— answered 12 months ago by Marcus Williams
answer permalink
9 Comments
  • I was able to reuse complex views in iOS, but not on android. I don't think that the reuse is causing the lag you're seeing, but if you were to create views from scratch, you certainly wouldn't see any old content when you open the detail window. I don't think it would hurt you from a performance perspective, and you'll be more prepared for your android work.

    My advice: don't wait until you've written hundreds of lines of code to start testing on android if your goal is a cross-platform app. You'll find that the differences between the platforms pile up quickly. If you are fighting 5 or 6 inconsistencies at once, it's going to be very hard to identify the problems. It's better to at least smoke test your code on both platforms fairly frequently.

    I've seen a lot of people on this forum who build an entire app on iOS, only to find that it crashes and burns on android. Many of them sour on the platform.

    But if you start on both platforms from the beginning and work methodically through each new feature on both platforms, you will eventually succeed.

    — commented 12 months ago by Jason Priebe

  • Thanks for the advise, I not to far in anyway so will start looking at Android straight away.

    In regards to loading the detail view from scratch you'll have to forgive me as I basically learning from examples of code. I have noticed that in the Master/Detail template provided the detail view is loaded differently for android. Is this what you mean?

    function ApplicationWindow() {
        //declare module dependencies
        var MasterView = require('ui/common/MasterView'),
            DetailView = require('ui/common/DetailView');
     
        //create object instance
        var self = Ti.UI.createWindow({
            title:'Products',
            exitOnClose:true,
            navBarHidden:false,
            backgroundColor:'#ffffff'
        });
     
        //construct UI
        var masterView = new MasterView();
        self.add(masterView);
     
        //add behavior for master view
        masterView.addEventListener('itemSelected', function(e) {
            //create detail view container
            var detailView = new DetailView();
            var detailContainerWindow = Ti.UI.createWindow({
                title:'Product Details',
                navBarHidden:false,
                backgroundColor:'#ffffff'
            });
            detailContainerWindow.add(detailView);
            detailView.fireEvent('itemSelected',e);
            detailContainerWindow.open();
        });
     
        return self;
    };
     
    module.exports = ApplicationWindow;

    — commented 12 months ago by Marcus Williams

  • That's exactly what I was thinking of -- you create the detailview each time the user selects an item from the master view.

    I am not familiar with the Titanium app templates, but as I look through the Master/Detail template, I can see that the Titanium developers already knew this -- you can reuse a complex window on iOS, but not on android. I wish they would have mentioned this somewhere. I had to find out the hard way. :-(

    — commented 12 months ago by Jason Priebe

  • Show 6 more comments

Your Answer

Think you can help? Login to answer this question!