2012-02-08 30 views
10

Khi tạo một giao diện tùy chỉnh, tôi đã nhận thấy rằng nhiều người dường như để làm điều đó như thế này:Tôi có nên gọi super() hoặc gọi phương thức này() cho các nhà xây dựng chế độ xem tùy chỉnh của Android không?

public MyView(Context context) { 
    super(context); 
    // this constructor used when programmatically creating view 
    doAdditionalConstructorWork(); 
} 

public MyView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    // this constructor used when creating view through XML 
    doAdditionalConstructorWork(); 
} 

private void doAdditionalConstructorWork() { 
    // init variables etc. 
} 

Vấn đề của tôi với điều này là nó dừng lại cho tôi từ việc biến tôi thức. Bất kỳ lý do nào không làm những điều sau đây?

public MyView(Context context) { 
    this(context, null); 
    // this constructor used when programmatically creating view 
} 

public MyView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
    // this constructor used when creating view through XML 
} 

public MyView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    // this constructor used where? 
    // init variables 
} 

Tôi đã có thể tạo chế độ xem tốt qua XML và thông qua mã, nhưng tôi không chắc chắn có bất kỳ hạn chế nào đối với phương pháp này hay không. Điều này sẽ làm việc trong mọi trường hợp?

another part to this question

+0

Gọi 'this' chỉ gọi một hàm tạo khác của lớp hiện tại. Tôi nghĩ rằng đây là một cái gì đó bạn đã không nhận ra. Như vậy 'this (context, null);' gọi 'public MyView (bối cảnh bối cảnh, AttributeSet attrs) {' mà lần lượt gọi 'publicView (ngữ cảnh bối cảnh, AttributeSet attrs, int defStyle) {'. Lời gọi hàm tạo này không phải là rất phổ biến trong ngôn ngữ java, nhưng tôi thấy không có lý do gì sẽ không hoạt động. –

+0

Tôi nhận ra rằng, tôi chỉ quan tâm đến các tham số. :) –

Trả lời

-5

Ok.

Khi chúng tôi xem xét nguồn của TextView.java.

Họ đã sử dụng cùng một hệ thống phân cấp.

Vì vậy, bạn đồng ý với phương pháp này.

+0

Mọi người bỏ phiếu này, vui lòng đề cập đến lý do. Tôi cũng đã thêm tham chiếu triển khai của chính Android. Câu trả lời này đúng với kịch bản cho trước của OP. –

-2

Yup, đó là một mô hình hợp lý để sử dụng, do đó bạn không phải lặp lại công việc tùy chỉnh trong mỗi một trong những nhà thầu của bạn. Và không, dường như không có bất kỳ hạn chế nào đối với phương pháp.

-2

Nó hoàn toàn phụ thuộc vào yêu cầu của bạn. Hãy cho chúng tôi nói nếu bạn muốn sử dụng bất kỳ phương thức nào trong lớp cha mà không ghi đè chức năng của chúng trong chế độ xem tùy chỉnh của bạn, thì bạn cần sử dụng super() và khởi tạo lớp cha. Nếu bạn không cần phải gọi bất kỳ phương thức nào trong lớp cha, tất cả các triển khai đều được ghi đè trong chế độ xem tùy chỉnh của bạn, thì bạn không cần. Đọc Ví dụ về chế độ xem tùy chỉnh trong số link này.

7

Hạn chế duy nhất tôi có thể thấy (mà không ai có vẻ đã đề cập) là nhà xây dựng thứ hai của bạn mất defStyle của siêu lớp, vì bạn đặt thành 0. Nhìn vào mã nguồn cho bất kỳ lớp Xem nào của Android và bạn sẽ nhận thấy rằng hàm tạo thứ hai luôn có một định nghĩa cụ thể là defStyle.

Ví dụ, đây là nhà xây dựng thứ hai của ListView:

public ListView(Context context, AttributeSet attrs) { 
    this(context, attrs, com.android.internal.R.attr.listViewStyle); 
} 

Nếu bạn đã mở rộng ListView sử dụng phương pháp thứ hai mà bạn mô tả, com.android.internal.R.attr.listViewStyle sẽ không còn là defStyle, bởi vì bạn muốn được bỏ qua đó là hàm tạo siêu thứ hai và làm cho nó bằng không. Tôi cho rằng bạn có thể giải quyết điều này bằng cách sử dụng cùng một defstyle như ListView, như vậy:

public MyView(Context context, AttributeSet attrs) { 
    this(context, attrs, android.R.attr.listViewStyle); 
} 

Nhưng nó không phải là chính xác "purist" bằng cách nào, bởi vì bạn đang nhân tạo buộc nó phải có cùng defStyle như ListView. Vì vậy, trái với những gì người khác nói, tôi thực sự nghĩ bạn nên sử dụng phương pháp doAdditionalConstructorWork() đầu tiên được nêu trong bài đăng của bạn, bởi vì ít nhất đảm bảo rằng defStyle được đặt chính xác.

+0

nhưng nhìn vào mã nguồn 'View' chúng ta có thể thấy rằng nó ** đặt **' defStyle' thành 0: 'public view (ngữ cảnh bối cảnh, AttributeSet attrs) { điều này (context, attrs, 0); } ' –

3

Sao chép điều này từ câu trả lời của tôi cho một câu hỏi tương tự.

Nếu bạn ghi đè tất cả ba nhà thầu, vui lòng KHÔNG CASCADE this(...) CUỘC GỌI. Thay vào đó, bạn nên thực hiện việc này:

public MyView(Context context) { 
    super(context); 
    init(context, null, 0); 
} 

public MyView(Context context, AttributeSet attrs) { 
    super(context,attrs); 
    init(context, attrs, 0); 
} 

public MyView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(context, attrs, defStyle); 
} 

private void init(Context context, AttributeSet attrs, int defStyle) { 
    // do additional work 
} 

Lý do là lớp cha có thể bao gồm các thuộc tính mặc định trong các hàm tạo riêng mà bạn có thể vô tình ghi đè. Ví dụ, đây là nhà xây dựng cho TextView:

public TextView(Context context) { 
    this(context, null); 
} 

public TextView(Context context, @Nullable AttributeSet attrs) { 
    this(context, attrs, com.android.internal.R.attr.textViewStyle); 
} 

public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    this(context, attrs, defStyleAttr, 0); 
} 

Nếu bạn không gọi super(context), bạn sẽ không phải thiết lập đúng R.attr.textViewStyle là attr phong cách.

Các vấn đề liên quan