DroidScript
DroidScript
разработка мобильных приложений

Групповые операции над объектами

DroidScript  
06.05.2017
Групповые операции над объектами позволяют улучшить структуру программного кода и устранить дублирующийся код.

Для единого стилевого оформления виджетов часть их свойств должна иметь одинаковые значения, например, размеры, цвет надписи и фона, размер шрифта и др. Для этого используются темы оформления, если они доступны, либо ручная настройка данных свойств. В примере ниже создаются три одинаковые кнопки, которые внешне отличаются только надписями на них.

Пример 1. Три одинаковые кнопки с индивидуальной настройкой свойств.

function OnStart()
{
   var _buttonFontSize = 20;
    
	var _lay = app.CreateLayout( "linear", "VCenter,FillXY" );	
	
	var _btn1 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 1' );
	    
	    _object.SetTextSize( _buttonFontSize, 'sp' );
	    
	    return _object;
	})();

	var _btn2 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 2' );
	    
	    _object.SetTextSize( _buttonFontSize, 'sp' );
	    
	    return _object;
	})();

	var _btn3 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 3' );
	    
	    _object.SetTextSize( _buttonFontSize, 'sp' );
	    
	    return _object;
	})();

    _lay.AddChild( _btn1 );
    _lay.AddChild( _btn2 );
    _lay.AddChild( _btn3 );

	app.AddLayout( _lay );
}

В этом примере размер шрифта задаётся индивидуально для каждого объекта, что и приводит к дублированию строки:

_object.SetTextSize( _buttonFontSize, 'sp' );

Размер шрифта задан при помощи переменной _buttonFontSize, единица измерения в виде 'sp'. Всё кажется неплохо. Предположим теперь, что таких кнопок 20 и захотелось изменить название переменной с _buttonFontSize на _menuFontSize. Придётся воспользоваться операцией поиска и замены в тексте. Это несложно, но чем больше код, тем небезопаснее её использование, так как увеличивается вероятность что-то случайно изменить и в остальном коде. Можно, конечно, производить замену в выделенной области, уточнять запрос для поиска, проверять каждое изменение в тексте и др., но гораздо проще и безопаснее для этого использовать вспомогательную внутреннюю функцию, в которой всем выбранным объектам будет присвоено нужное значение свойства.

Пример 2. Групповая операция.

function OnStart()
{
    function SetTextSize( p_objectList ){
        
        for( var _i = 0, _iMax = p_objectList.length; _i < _iMax; _i++ ){
            
            p_objectList[ _i ].SetTextSize( _buttonFontSize, 'sp' );
        }
    }

   var _buttonFontSize = 20;
    
	var _lay = app.CreateLayout( "linear", "VCenter,FillXY" );	
	
	var _btn1 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 1' );
	    
	    return _object;
	})();

	var _btn2 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 2' );
	    
	    return _object;
	})();

	var _btn3 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 3' );
	    
	    return _object;
	})();

    SetTextSize([
       _btn1,
       _btn2,
       _btn3
    ]);

    _lay.AddChild( _btn1 );
    _lay.AddChild( _btn2 );
    _lay.AddChild( _btn3 );

	app.AddLayout( _lay );
}

При помощие вложеной функции SetTextSize мы устранили дублирование кода, но вместе с этим получили дублирование действий, которое заключается в необходимости создания отдельных функций для выполнения каждой операции. Например, для изменения размеров кнопок нужно будет создать функцию SetSize, для изменения цвета фона - функцию SetBackColor и т.д. Избавиться от этого поможет функция с динамической генерацией методов. Для этого воспользуемся конструктором функций Function (метод applay для объектов API DroidScript не реализован).

Пример 3. Группировка действий.

function OnStart()
{
    function runMethodNot( p_method, p_objectList ){

        var p_method = 'p_object.' + p_method;
 
        var _func = new Function( "p_object", p_method );
               
        for( var _i = 0, _iMax = p_objectList.length; _i < _iMax; _i++ ){
            
            _func( p_objectList[ _i ] );
        }
    }

   var _object = new Object();

   var _buttonFontSize = 20;
   var _buttonFontDim = '"sp"';
   var _buttonBackColor = '"red"';
    
	var _lay = app.CreateLayout( "linear", "VCenter,FillXY" );	
	
	var _btn1 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 1' );
	    
	    return _object;
	})();

	var _btn2 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 2' );
	    
	    return _object;
	})();

	var _btn3 = (function(){
	    
	    var _object = app.CreateButton( 'Кнопка 3' );
	    
	    return _object;
	})();

	//+++ блок настройки одинаковых свойств

	runMethodNot( 'SetTextSize(' + _buttonFontSize + ',' + _buttonFontDim + ')',
    [
       _btn1,
       _btn2,
       _btn3
    ]);

    runMethodNot( 'SetBackColor(' + _buttonBackColor + ')',
    [
       _btn1,
       _btn3
    ]);

	//--- блок настройки одинаковых свойств

	_lay.AddChild( _btn1 );
   _lay.AddChild( _btn2 );
	_lay.AddChild( _btn3 );
    
	app.AddLayout( _lay );
}

Размер кода в примере 3 больше, чем в исходном примере 1, но его структура проще и понятнее: уникальные значения свойств кнопок (текст надписи) задаются при их создании, а установка идентичных значений свойств (размер шрифта и цвет фона) вынесена в отдельный блок кода.

В показанных примерах список (массив) объектов задаётся вручную. Это позволяет передавать объекты разных типов, которые принадлежат разным компоновщикам. Если это не требуется, то можно автоматизировать процесс путём организации перебора элементов, принадлежащих тому или иному компоновщику.

Теперь рассмотрим код компоновки:

	_lay.AddChild( _btn1 );
	_lay.AddChild( _btn2 );
  	_lay.AddChild( _btn3 );
    

Недостатками такой записи является дублирование кода и возможность использования метода AddChild в любом месте кода. В результате эти методы разбросаны по всему коду инициализации и становится сложно понять, какие объекты, где и какому компоновщику добавлены. Для устранения путаницы создадим ещё одну функцию addChild для группового добавления элементов компоновщику:

function addChild( p_layout, p_elements ){

    for( var _i = 0; _i < p_elements.length; _i++){
        
        p_layout.AddChild( p_elements[_i] );
    }
}

Её вызов производится так:

addChild( _lay,
[
	_btn1,
    _btn2,
    _btn3
]);

Похожим образом можно реализовать и другие групповые операции над объектами.

DroidScript  
© 2016-2022  Александр Страшко