Can I use refactoring to exchange the type of a variable for another?
Short Answer
The function you are looking for is Type Migration!
A Type Migration can be performed by right clicking on the type of a variable or field and then selecting Refactor -> Type Migration. Alternatively you can use these keyboard shortcuts:
- On a Mac: Shift + ⌘ + F6
- On Windows: Shift + Ctrl + F6
Just choose the type you want to migrate to, click refactor and Android Studio starts working its magic!
Long and more detailed Answer
You seem to misunderstand what Rename actually does.
Rename can be used to literally rename elements. So you can change the name of a variable, parameter, method or class with it. For example if you have a class named Foo
and you want to change its name to Bar
you can do that easily with Rename.
But you cannot rename LinearLayout
since it is framework class and those of course cannot be modified. This however shouldn't be a problem at all because you don't actually want to rename LinearLayout
, do you? What you actually want to do is change the type from LinearLayout
to RelativeLayout
. And there is another very useful refactor feature to do exactly that, it is called Type Migration.
You can perform a Type Migration by right clicking on any variable whose type you want to exchange for another and then selecting Refactor -> Type Migration. After that a Dialog pops up and you can enter the type you want to migrate to, in your case RelativeLayout
. Then just click Refactor
and Android Studio starts working its magic. There may be an additional popup window informing you of all the things in your code which cannot be migrated automatically. Just scan through the list of conflicts and when you are done hit Ignore and fix those conflicts manually.
Here is an example of Type Migration at work. I started out with this code:
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) {
...
}
Now I performed a Type Migration to RelativeLayout
on the local variable layout
in doStuff()
. The result looks like this:
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) {
...
}
As you can see Type Migration did excellent work. The type of the field and even the type of the parameter of fooTheBar()
was changed to RelativeLayout
. There was only one conflict. Android Studio couldn't automatically change the type of the cast at the very top of doStuff()
. I had to fix that manually. As I mentioned earlier I was warned about this conflict while performing the refactoring.
You could of course ask yourself why it could change the type of the field and the parameter automatically but couldn't change the type of a cast, but if you think about it that actually makes a lot of sense:
The part of the code it couldn't migrate automatically was (LinearLayout) container.findViewById(R.id.linearLayout)
. This method of course looks for a View
with the id R.id.linearLayout
. This View
might be defined in a layout xml or it may be added to the container
dynamically at runtime but in any case it is not something which can just be refactored automatically without the risk of breaking functionality. It is something only the developer can decide how to handle and that's why you are warned about it.