Могу ли я использовать рефакторинг для обмена типа переменной для другого?

Android Studio обеспечивает мощный рефакторинг, например Rename. Я могу использовать его для изменения имени переменных, полей, параметров, однако я не могу найти способ переименовать тип. Например:

LinearLayout layout = (LinearLayout) v.findViewById(....);
// ........
// A bunch of code using `layout` many times

Как я могу быстро реорганизовать LinearLayout на RelativeLayout и применить его к остальной части кода? И могу ли я сделать то же самое для полей?

Ответы

Ответ 1

Краткий ответ

Функция, которую вы ищете, это Type Migration!

A Type Migration можно выполнить, щелкнув правой кнопкой мыши по типу переменной или поля, а затем выбрав RefactorType Migration. В качестве альтернативы вы можете использовать эти сочетания клавиш:

  • На Mac: Shift + + F6
  • В Windows: Shift + Ctrl + F6

Просто выберите тип, на который вы хотите перейти, нажмите "Рефакторинг", и Android Studio начнет работать с магией!


Длинный и более подробный ответ

Вы, кажется, неправильно понимаете, что на самом деле делает Rename.

Rename может использоваться для буквального переименования элементов. Таким образом, вы можете сменить имя переменной, параметра, метода или класса. Например, если у вас есть класс с именем Foo и вы хотите изменить его имя на Bar, вы можете легко сделать это с помощью Rename.

Но вы не можете переименовать LinearLayout, так как это класс framework, и, конечно, его нельзя изменить. Это, однако, не должно быть проблемой вообще, потому что вы действительно не хотите переименовывать LinearLayout, не так ли? Вы действительно хотите изменить тип от LinearLayout до RelativeLayout. И есть еще одна очень полезная функция рефакторинга, которая делает именно это, она называется Type Migration.

Вы можете выполнить Type Migration, щелкнув правой кнопкой мыши на любой переменной, тип которой вы хотите обменять на другую, а затем выберите RefactorType Migration. После этого открывается диалоговое окно, и вы можете ввести тип, к которому хотите перейти, в вашем случае RelativeLayout. Затем просто нажмите Refactor, и Android Studio начнет работать с магией. Может появиться дополнительное всплывающее окно, информирующее вас обо всех вещах вашего кода, которые невозможно перенести автоматически. Просто просмотрите список конфликтов и, когда вы закончите, нажмите Ignore и исправьте эти конфликты вручную.

Вот пример Type Migration на работе. Я начал с этого кода:

private LinearLayout mLayout;

private void doStuff(ViewGroup container) {
    LinearLayout layout = (LinearLayout) container.findViewById(0);

    layout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ...
        }
    });

    mLayout = layout;
    fooTheBar(layout);   
}

private void fooTheBar(LinearLayout layout) {
    ...
}

Теперь я выполнил от Type Migration до RelativeLayout локальную переменную layout в doStuff(). Результат выглядит следующим образом:

private RelativeLayout mLayout;

private void doStuff(ViewGroup container) {
    // Here is the only conflict which could not be refactored automatically.
    // I had to change the cast to RelativeLayout manually.
    RelativeLayout layout = (LinearLayout) container.findViewById(R.id.linearLayout);

    layout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ...
        }
    });

    mLayout = layout;
    fooTheBar(layout);
}

private void fooTheBar(RelativeLayout layout) {
    ...
}

Как вы можете видеть, Type Migration сделал отличную работу. Тип поля и тип параметра fooTheBar() был изменен на RelativeLayout. Был только один конфликт. Android Studio не может автоматически изменить тип роли в самой верхней части doStuff(). Я должен был исправить это вручную. Как я упоминал ранее, я был предупрежден об этом конфликте при выполнении рефакторинга.

Конечно, вы можете спросить себя, почему это может изменить тип поля и параметр автоматически, но не может изменить тип приведения, но если вы подумаете об этом, это на самом деле имеет большой смысл:

Часть кода, который он не мог выполнить автоматически, был (LinearLayout) container.findViewById(R.id.linearLayout). Конечно, этот метод ищет a View с id R.id.linearLayout. Этот View может быть определен в макете xml или может быть добавлен к container динамически во время выполнения, но в любом случае это не то, что можно просто реорганизовать автоматически без риска нарушения функциональности. Это то, что разработчик может решить, как обращаться и почему вас предупреждают об этом.

Ответ 2

Для Type Migration в файле Kotlin:

Скажем, вы хотите изменить входной параметр с String на Int в следующей функции.

fun getValue(key: String){
}
  1. Поместите курсор на тип, который вы хотите изменить (в данном случае String)

  2. Right click> Refactor> Change Signature. Или используйте ярлыки ниже для этого шага:

    • Mac: + F6
    • Windows: Ctrl + F6 (не тестировалось)
  3. После завершения шага 2 откроется это окно, щелкните строку, выделенную синим цветом:

  1. Замените тип тем, что вы хотите, и нажмите Refactor