chuyển đổi câu lệnh trường hợp lỗi: biểu thức trường hợp phải là biểu thức không đổi


128

Tuyên bố trường hợp chuyển đổi của tôi hoạt động hoàn toàn tốt ngày hôm qua. Nhưng khi tôi chạy mã vào sáng sớm hôm nay nhật thực đã xảy ra lỗi cho tôi khi gạch chân các câu lệnh trường hợp có màu đỏ và nói: các biểu thức trường hợp phải là biểu thức không đổi, đó là hằng số tôi không biết điều gì đã xảy ra. Đây là mã của tôi dưới đây:

public void onClick(View src)
    {
        switch(src.getId()) {
        case R.id.playbtn:
            checkwificonnection();
            break;

        case R.id.stopbtn:
            Log.d(TAG, "onClick: stopping srvice");
            Playbutton.setImageResource(R.drawable.playbtn1);
            Playbutton.setVisibility(0); //visible
            Stopbutton.setVisibility(4); //invisible
            stopService(new Intent(RakistaRadio.this,myservice.class));
            clearstatusbar();
            timer.cancel();
            Title.setText(" ");
            Artist.setText(" ");
            break;

        case R.id.btnmenu:
            openOptionsMenu();
            break;
        }
    }

Tất cả R.id.int đều được gạch chân màu đỏ.


Bạn có thể cung cấp định nghĩa của R.id.playbtnvv? Là tất cả mọi thứ tĩnh và cuối cùng?
Thomas

2
Có lẽ bạn đã xóa / sửa đổi bố cục của mình và những id đó không còn tồn tại nữa hoặc đại loại như thế ...
Vicente Plata

Lớp Rthường được tạo bởi các công cụ IDE / dev, do đó, nó thường đúng với phiên bản Android đang sử dụng.
cHao

R.id. * của tôi đều ổn và tồn tại trong lớp gen của Android .. và nó cũng có trong bố cục chính.
HeartlessArchangel

Câu trả lời:


274

Trong một dự án Android thông thường, các hằng số trong lớp R tài nguyên được khai báo như sau:

public static final int main=0x7f030004;

Tuy nhiên, kể từ ADT 14, trong một dự án thư viện, chúng sẽ được khai báo như sau:

public static int main=0x7f030004;

Nói cách khác, các hằng số không phải là cuối cùng trong một dự án thư viện. Do đó mã của bạn sẽ không còn được biên dịch.

Giải pháp cho việc này rất đơn giản: Chuyển đổi câu lệnh switch thành câu lệnh if-other.

public void onClick(View src)
{
    int id = src.getId();
    if (id == R.id.playbtn){
        checkwificonnection();
    } else if (id == R.id.stopbtn){
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
    } else if (id == R.id.btnmenu){
        openOptionsMenu();
    }
}

http://tools.android.com/tips/non-constant-fields

Bạn có thể nhanh chóng chuyển đổi một switchcâu lệnh thành một if-elsecâu lệnh bằng cách sử dụng như sau:

Trong Eclipse
Di chuyển con trỏ của bạn đến switchtừ khóa và nhấn Ctrl+ 1sau đó chọn

Chuyển đổi 'chuyển đổi' thành 'nếu khác'.

Trong Android Studio
Di chuyển con trỏ của bạn đến switchtừ khóa và nhấn Alt+ Entersau đó chọn

Thay thế 'công tắc' bằng 'nếu'.


tôi thay đổi câu lệnh chuyển đổi trường hợp của mình thành câu lệnh if-if khác .. Nó làm tôi băn khoăn không biết tôi tạo một dự án Android mới và sử dụng câu lệnh chuyển đổi trường hợp và hoạt động tốt ..
HeartlessArchangel

1
Có thể là dự án đầu tiên của bạn đang sử dụng một dự án thư viện và dự án mới của bạn thì không.
Benito Bertoli

Tôi không hiểu rằng xin lỗi tôi thực sự là người mới bắt đầu ở đây .. bạn có thể giải thích
HeartlessArchangel

7
Ít nhất nhật thực sẽ cho phép bạn chuyển đổi sang if / other tự động. nhấp vào từ khóa chuyển đổi. sau đó nhấn ctrl-1
Darren Cato

1
Trình biên dịch cần biểu thức được biết đến tại thời điểm biên dịch. Không có finaltừ khóa, một biến có thể được thay đổi trong thời gian chạy.
Benito Bertoli

52

Bỏ chọn "Is Library" trong dự án Thuộc tính làm việc cho tôi.


2
Nhấp chuột phải vào tên dự án của bạn. Sau đó bấm vào thuộc tính -> Android. Ở phía dưới bên phải của cửa sổ bật lên là phần "Thư viện". Trong đó, nếu tùy chọn "là Thư viện" được chọn, hãy bỏ chọn nếu bạn không muốn dự án của mình là dự án thư viện. Sau đó làm sạch và xây dựng lại. Nếu bạn muốn nó là một dự án thư viện, thì bạn phải thay đổi công tắc của mình thành một điều kiện khác nếu được nêu ở nơi khác.
VikingGlen

5
Có nhiều lý do tại sao một dự án thư viện được đánh dấu bằng "Is Library". Đây không phải là một giải pháp thích hợp cho vấn đề - nó sẽ phá vỡ cấu trúc dự án Android của bạn bằng cách tạo ra những thư viện nên hoạt động như các ứng dụng thông thường.
ADTC

13

Giải pháp có thể được thực hiện theo cách này:

  1. Chỉ cần gán các giá trị để Integer
  2. Hãy biến để thức

Thí dụ:

public static final int cameraRequestCode = 999;

Hy vọng điều này sẽ giúp bạn.


8

R.id. *, vì ADT 14 không được khai báo nhiều hơn là int tĩnh cuối cùng nên bạn không thể sử dụng trong cấu trúc trường hợp chuyển đổi. Bạn có thể sử dụng nếu mệnh đề khác thay thế.


vâng tôi đã đọc nó trên tools.android.com, tôi cũng đã cố gắng tạo một dự án mới và sử dụng mã ở trên và nó hoạt động tốt .. nó thế nào?
HeartlessArchangel


6
Tại sao họ thực hiện thay đổi này là vô nghĩa.
Andrew S

8

Giải pháp đơn giản cho vấn đề này là:

Nhấp vào công tắc và sau đó nhấn CTL + 1, Nó sẽ thay đổi công tắc của bạn thành câu lệnh chặn if-other và sẽ giải quyết vấn đề của bạn


7

Làm thế nào về giải pháp khác này để giữ cho chuyển đổi tốt đẹp thay vì một if-other:

private enum LayoutElement {
    NONE(-1),
    PLAY_BUTTON(R.id.playbtn),
    STOP_BUTTON(R.id.stopbtn),
    MENU_BUTTON(R.id.btnmenu);

    private static class _ {
        static SparseArray<LayoutElement> elements = new SparseArray<LayoutElement>();
    }

    LayoutElement(int id) {
        _.elements.put(id, this);
    }

    public static LayoutElement from(View view) {
        return _.elements.get(view.getId(), NONE);
    }

}

Vì vậy, trong mã của bạn, bạn có thể làm điều này:

public void onClick(View src) {
    switch(LayoutElement.from(src)) {
    case PLAY_BUTTTON:
        checkwificonnection();
        break;

    case STOP_BUTTON:
        Log.d(TAG, "onClick: stopping srvice");
        Playbutton.setImageResource(R.drawable.playbtn1);
        Playbutton.setVisibility(0); //visible
        Stopbutton.setVisibility(4); //invisible
        stopService(new Intent(RakistaRadio.this,myservice.class));
        clearstatusbar();
        timer.cancel();
        Title.setText(" ");
        Artist.setText(" ");
        break;

    case MENU_BUTTON:
        openOptionsMenu();
        break;
    }
}

Enums là tĩnh nên điều này sẽ có tác động rất hạn chế. Cửa sổ duy nhất cần quan tâm sẽ là tra cứu kép có liên quan (đầu tiên là trên SpzzyArray bên trong và sau đó trên bảng chuyển đổi)

Điều đó nói rằng, enum này cũng có thể được sử dụng để lấy các mục một cách trôi chảy, nếu cần bằng cách giữ một tham chiếu đến id ... nhưng đó là một câu chuyện trong một thời gian khác.


Enums không được khuyến khích trong Android do sự phình to bộ nhớ của chúng; và đó là lý do chính tại sao chúng không bao giờ được sử dụng trong AOSP - và lý do tại sao bạn thấy ints ở khắp mọi nơi.
ADTC


3

Đó là lỗi cho tôi khi tôi sử dụng switch trong một hàm với các biến được khai báo trong lớp:

private void ShowCalendar(final Activity context, Point p, int type) 
{
    switch (type) {
        case type_cat:
            break;

        case type_region:
            break;

        case type_city:
            break;

        default:
            //sth
            break;
    }
}

Vấn đề đã được giải quyết khi tôi khai báo finalcác biến khi bắt đầu lớp:

final int type_cat=1, type_region=2, type_city=3;

1
enumlà một thay thế tốt hơn inttrong trường hợp này. Người gọi phương thức sẽ không thể gọi hàm với loại không hợp lệ.
nhahtdh

tôi có các kiểu int cụ thể vì vậy nó ổn nếu tôi sử dụng ints. Tuy nhiên tôi muốn biết một ví dụ với enum: D
aimiliano

i have specific int types so its ok if i use intsKhông thực sự có ý nghĩa. Về ví dụ enum: docs.oracle.com/javase/tutorial/java/javaOO/enum.html
nhahtdh

ý tôi là kiểu biến int đến trong hàm sẽ luôn là một trong 3 kiểu này vì vậy nó sẽ không phá vỡ bất cứ điều gì nhờ vào ví dụ enum :)
aimiliano

i mean that the incoming int variable type in the function will always be one of these 3 types so it won't break anythingĐây là giả định của bạn . Một số người khác có thể gọi hàm không chính xác với số tùy ý. Với enum, bạn không cần phải giả sử, nó được thi hành bởi ngôn ngữ.
nhahtdh

2

Tôi muốn đề cập rằng, tôi đã gặp tình huống tương tự khi tôi cố gắng thêm một thư viện vào dự án của mình. Đột nhiên tất cả các báo cáo chuyển đổi bắt đầu hiển thị lỗi!

Bây giờ tôi đã cố xóa thư viện mà tôi đã thêm, thậm chí sau đó nó không hoạt động. làm thế nào " khi tôi làm sạch dự án " tất cả các lỗi đã xảy ra!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.