অ্যান্ড্রয়েড কাস্টম ভিউয়ের জন্য আমার কি তিনটি কনস্ট্রাক্টরের দরকার?


142

একটি কাস্টম ভিউ তৈরি করার সময়, আমি লক্ষ্য করেছি যে অনেক লোক এটিকে এটি করে বলে মনে হচ্ছে:

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.
}

আমার প্রথম প্রশ্ন, কনস্ট্রাক্টর সম্পর্কে কী MyView(Context context, AttributeSet attrs, int defStyle)? এটি কোথায় ব্যবহৃত হয়েছে তা আমি নিশ্চিত নই, তবে আমি এটি সুপার ক্লাসে দেখছি। আমার কি এটি দরকার এবং এটি কোথায় ব্যবহৃত হয়?

আছে এই প্রশ্নের অন্য অংশ

উত্তর:


144

আপনি যদি পছন্দ Viewথেকে নিজের কাস্টম যুক্ত করেন তবে xml:

 <com.mypack.MyView
      ...
      />

আপনার কনস্ট্রাক্টরের দরকার হবে public MyView(Context context, AttributeSet attrs), অন্যথায় Exceptionঅ্যান্ড্রয়েড যখন আপনার স্ফীত করার চেষ্টা করবে তখন আপনি এটি পাবেন View

আপনি যদি এগুলি যোগ Viewকরেন xmlএবং android:styleবৈশিষ্ট্যগুলিও নির্দিষ্ট করেন তবে :

 <com.mypack.MyView
      style="@styles/MyCustomStyle"
      ...
      />

২ য় কনস্ট্রাক্টরকে MyCustomStyleস্পষ্ট এক্সএমএল বৈশিষ্ট্য প্রয়োগ করার আগে ডাকা হবে এবং শৈলীতে ডিফল্ট করা হবে ।

তৃতীয় নির্মাণকারী সাধারণত ব্যবহৃত হয় যখন আপনি নিজের অ্যাপ্লিকেশনটির সমস্ত দর্শন একই স্টাইলের চান।


3
তখন প্রথম কনস্ট্রাক্টর কখন ব্যবহার করবেন?
অ্যান্ড্রয়েড খুনি

@ অভিডিউ ল্যাটকু আপনি কি দয়া করে তৃতীয় সিটিওআর এর একটি উদাহরণ (3 টি পরামিতি সহ) দেখাতে পারেন?
অ্যান্ড্রয়েড বিকাশকারী

আমি কি কনস্ট্রাক্টরের অতিরিক্ত পরামিতি যুক্ত করতে পারি এবং আমি কীভাবে সেগুলি ব্যবহার করতে পারি?
মোহাম্মদ সুহি শেখ কুরুউশ

24
তৃতীয় কন্সট্রাকটর সংক্রান্ত, এই আসলে সম্পূর্ণ ভুল । এক্সএমএল সর্বদা দ্বি-যুক্তিযুক্ত কনস্ট্রাক্টরকে কল করে। তিন-যুক্তি (এবং চার-যুক্তি ) নির্মাণকারীকে সাবক্লাস দ্বারা ডাকা হয় যদি তারা কোনও ডিফল্ট শৈলী, বা একটি ডিফল্ট শৈলী সরাসরি (চতুর্থ যুক্তিযুক্ত কনস্ট্রাক্টরের ক্ষেত্রে) যুক্ত কোনও বৈশিষ্ট্য নির্দিষ্ট করতে চান
imgx64

আমি উত্তরটি সঠিক করার জন্য একটি সম্পাদনা জমা দিয়েছি। আমি নীচে একটি বিকল্প উত্তর প্রস্তাব করেছি।
mbonnin

117

আপনি যদি তিনটি কনস্ট্রাক্টরকে ওভাররাইড করেন তবে দয়া করে this(...)কলগুলিতে ক্যাসকেড করবেন না । পরিবর্তে আপনার এটি করা উচিত:

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
}

কারণটি হ'ল পিতামাত্ত শ্রেণীর নিজস্ব নির্মাণকারীদের মধ্যে ডিফল্ট বৈশিষ্ট্যগুলি অন্তর্ভুক্ত থাকতে পারে যা আপনি দুর্ঘটনাক্রমে ওভাররাইড করে। উদাহরণস্বরূপ, এটি এর জন্য নির্মাতা 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);
}

যদি আপনি কল super(context)না করেন তবে আপনি সঠিকভাবে R.attr.textViewStyleস্টাইল অ্যাটর্স হিসাবে সেট করবেন না ।


12
তালিকাভিউ বাড়ানোর সময় এটি প্রয়োজনীয় পরামর্শ। উপরের এই-ক্যাসকেডিংয়ের একজন (পূর্ববর্তী) অনুরাগী হিসাবে, আমি প্রতিটি কনস্ট্রাক্টরের জন্য সঠিক সুপার পদ্ধতিটি কল করার সময় কেটে গিয়েছিলাম এমন একটি সূক্ষ্ম বাগটি খুঁজে বের করার সময়গুলি মনে করি।
গ্রোভ 60

BTW @Jin আমি এই উত্তর কোড ব্যবহৃত: stackoverflow.com/a/22780035/294884 যা আপনার উত্তর উপর ভিত্তি করে করা বলে মনে হয় - কিন্তু দয়া করে মনে রাখবেন লেখক Inflator ব্যবহার অন্তর্ভুক্ত?
ফ্যাটি

1
আমি মনে করি যে সমস্ত কন্সট্রাক্টরের ডিআর কল করা প্রয়োজনীয় নয়, কারণ আপনি যখন কল কলক্রম অনুসরণ করেন, আপনি প্রোগ্রামেটিক ভিউ তৈরির জন্য পূর্বনির্ধারিত কনস্ট্রাক্টারে যাইহোক দেখুন (প্রসঙ্গে প্রসঙ্গ) {}
মেরিয়ান ক্লিস্প্পিজ

আমি একই কাজ করছি কিন্তু পাঠ্যদর্শনটিতে মানগুলি সেট করতে ব্যর্থ হয়েছি যা আমার কাস্টম ভিউতে পাওয়া যায় আমি ক্রিয়াকলাপ থেকে মান সেট করতে চাই
এরুম

1
আমি এটা কখনই জানতাম না?
সুরগাচ

49

মাইভিউ (প্রসঙ্গে প্রসঙ্গ)

প্রোগ্রামিয়ালি ভিউগুলি তাত্পর্যপূর্ণ করার সময় ব্যবহৃত হয়।

মাইভিউ (প্রসঙ্গে প্রসঙ্গ, অ্যাট্রিবিউটসেট অ্যাটর্স)

LayoutInflaterএক্সএমএল বৈশিষ্ট্য প্রয়োগ করতে ব্যবহার করে । যদি এই বৈশিষ্ট্যের একটির নাম দেওয়া হয় style, বৈশিষ্ট্যগুলি বিন্যাসের এক্সএমএল ফাইলে সুস্পষ্ট মানগুলির সন্ধান করার আগে শৈলীটি দেখানো হবে।

মাইভিউ (প্রসঙ্গে প্রসঙ্গ, অ্যাট্রিবিউটসেট অ্যাটর্স, ইনফেস স্টাইলআটার)

মনে করুন আপনি styleপ্রতিটি লেআউট ফাইলটিতে উল্লেখ না করেই সমস্ত উইজেটে ডিফল্ট স্টাইল প্রয়োগ করতে চান । উদাহরণস্বরূপ, সমস্ত চেকবক্সকে ডিফল্টরূপে গোলাপী করুন। আপনি এটি DefStyleAttr দিয়ে করতে পারেন এবং ফ্রেমওয়ার্কটি আপনার থিমের ডিফল্ট শৈলীর সন্ধান করবে।

দ্রষ্টব্য যে কিছু সময় আগে defStyleAttrভুলভাবে নামকরণ করা হয়েছিল defStyleএবং এই নির্মাণকারীর সত্যই প্রয়োজন আছে কিনা তা নিয়ে কিছু আলোচনা রয়েছে। Https://code.google.com/p/android/issues/detail?id=12683 দেখুন

মাইভিউ (প্রসঙ্গে প্রসঙ্গ, অ্যাট্রিবিউটসেট অ্যাটর্সস, ইনফ ডেফস্টাইলআটার, ইনফ ডিস্টাইলআরেস)

অ্যাপ্লিকেশনগুলির বেস থিমের উপর আপনার নিয়ন্ত্রণ থাকলে 3 য় কনস্ট্রাক্টর ভাল কাজ করে। এটি গুগলের জন্য কাজ করছে কারণ তারা তাদের উইজেটগুলি ডিফল্ট থিমগুলির পাশাপাশি চালিত করে। তবে ধরুন আপনি একটি উইজেট লাইব্রেরি লিখছেন এবং আপনার ব্যবহারকারীদের থিমটি সাময়িক করার প্রয়োজন ছাড়াই আপনি একটি ডিফল্ট স্টাইল সেট করতে চান। আপনি এখন defStyleResএটি প্রথম 2 টি নির্মাণকারীর ডিফল্ট মান সেট করে ব্যবহার করতে পারেন :

public MyView(Context context) {
  super(context, null, 0, R.style.MyViewStyle);
  init();
}

public MyView(Context context, AttributeSet attrs) {
  super(context, attrs, 0, R.style.MyViewStyle);
  init();
}

সর্বেসর্বা

আপনি যদি নিজের মতামত বাস্তবায়ন করেন তবে কেবলমাত্র 2 জন প্রথম নির্মাণকারীর প্রয়োজন হবে এবং ফ্রেমওয়ার্ক দ্বারা কল করা যেতে পারে।

আপনি যদি নিজের দৃষ্টিভঙ্গিগুলি বর্ধনযোগ্য হতে চান তবে আপনি আপনার শ্রেণীর বাচ্চাদের গ্লোবাল স্টাইলিং ব্যবহার করতে সক্ষম হতে চতুর্থ নির্মাতা বাস্তবায়ন করতে পারেন।

আমি 3 য় নির্মাণকারীর জন্য বাস্তব ব্যবহারের কেস দেখতে পাচ্ছি না। আপনি যদি আপনার উইজেটের জন্য একটি ডিফল্ট স্টাইল না সরবরাহ করেন তবে আপনার ব্যবহারকারীরা এটি করতে সক্ষম হতে পারে তবে একটি শর্টকাট হতে পারে। এতটা হওয়া উচিত নয়।


7

কোটলিন মনে হয় এই ব্যথা অনেকটাই সরিয়ে নিয়েছে:

class MyView
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
    : View(context, attrs, defStyle)

@ জেভিএম ওভারলোডগুলি প্রয়োজনীয় সমস্ত নির্মাণকারী তৈরি করবে (সেই টীকাটির ডকুমেন্টেশন দেখুন ), যার প্রতিটি সম্ভবত সম্ভবত সুপার () বলে। তারপরে, কেবল আপনার প্রারম্ভিককরণের পদ্ধতিটি কোনও কোটলিন ডিআইআই}} ব্লকের সাথে প্রতিস্থাপন করুন। বয়লারপ্লেট কোড চলে গেল!


1

তৃতীয় নির্মাণকারী আরও জটিল complicated আমাকে একটি উদাহরণ রাখুন hold

সাপোর্ট-ভি 7 SwitchCompactপ্যাকেজটি 24 সংস্করণ থেকে সমর্থন করে thumbTintএবং trackTintবৈশিষ্ট্যগুলি সরবরাহ করে যখন 23 টি সংস্করণ তাদের সমর্থন করে না ow এখন আপনি তাদের 23 টি সংস্করণে সমর্থন করতে চান এবং আপনি এটি কীভাবে অর্জন করবেন?

আমরা কাস্টম ভিউ SupportedSwitchCompactপ্রসারিত ব্যবহার করে ধরে নিই SwitchCompact

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

public SupportedSwitchCompat(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public SupportedSwitchCompat(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init(){
    mThumbDrawable = getThumbDrawable();
    mTrackDrawable = getTrackDrawable();
    applyTint();
}

এটি একটি traditionalতিহ্যবাহী কোড শৈলী। নোট আমরা এখানে তৃতীয় পরম যাও 0 পাস । আপনি যখন কোডটি চালাবেন, আপনি getThumbDrawable()সর্বদা নালাগুলি ফিরে দেখতে পাবেন এটি কতটা অদ্ভুত কারণ পদ্ধতিটি getThumbDrawable()এর সুপার ক্লাসের SwitchCompactপদ্ধতি।

যদি আপনি R.attr.switchStyleতৃতীয় পরম পাস করেন, তবে সবকিছু ঠিকঠাক হয়? তবে কেন?

তৃতীয় পরম একটি সাধারণ বৈশিষ্ট্য। বৈশিষ্ট্যটি একটি স্টাইলের উত্সকে নির্দেশ করে above উপরের ক্ষেত্রে, সিস্টেমটি switchStyleবর্তমান থিমটিতে বৈশিষ্ট্যটি সন্ধান করবে ভাগ্যক্রমে সিস্টেম এটি সন্ধান করে।

ইন frameworks/base/core/res/res/values/themes.xml, আপনি দেখতে পাবেন:

<style name="Theme">
    <item name="switchStyle">@style/Widget.CompoundButton.Switch</item>
</style>

-2

আপনি যদি এখন আলোচনার মতো তিনটি নির্মাতা অন্তর্ভুক্ত করতে চান তবে আপনি এটিও করতে পারেন could

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

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

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

}

2
@ জিন এটি অনেক ক্ষেত্রে একটি ভাল ধারণা, তবে এটি অনেক ক্ষেত্রেই নিরাপদ (যেমন: রিলেটিভলআউট, ফ্রেমলাইআউট, রিসাইক্লারভিউ ইত্যাদি)। সুতরাং, আমি বলব এটি সম্ভবত কেস বাই কেস প্রয়োজনীয়তা এবং ক্যাসকেড করার সিদ্ধান্ত নেওয়ার আগে বেস ক্লাসটি পরীক্ষা করা উচিত। মূলত, যদি বেস শ্রেণিতে 2-প্যারাম নির্মাণকারী কেবল এইটিকে (প্রসঙ্গ, অনুগ্রহক, 0) কল দিচ্ছেন তবে কাস্টম ভিউ ক্লাসে এটি করা নিরাপদ।
এজেডব্লিউ

@ আইয়ানওয়ং অবশ্যই এটি বলা হবে, কারণ প্রথম এবং দ্বিতীয় পদ্ধতিগুলি তৃতীয় কল করছে।
কুলমাইন্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.