1- با اضافه کردن خاصیت android:supportsRtl="true"
در تگ application فایل AndroidManifiest.xml، مشکل راست به چپ صفحات preferences تون حل خواهد شد. (برای اندروید 4.2 به بعد)
2- آیا میدونید هیچ تفاوتی بین fill_parent و match_parent در خاصیت عناصر گرافیکی وجود نداره و هر دو دارای مقدار 1- هستند؟
این مسئله فقط یک تغییر نام جزیی بوده که از API 8 به بعد صورت گرفته و پیشنهاد شده که از match_parent استفاده بشه.
3- از انجایی که SharedPreference
ها عملیات read/write برروی دیسک انجام میدن و معمولاً هم در متد OnCreate()
یا OnResume()
فراخوانی و load می شن، پس بهتره در thread غیر از UI اعمال بشن، تا برنامه رو دچار وقفه نکنن.
همچنین لازم نیست نگران تعدد عملیات باشید، چراکه SharedPreference یک شی Singleton هست و فقط یکبار بارگذاری میشه.
4- در بیشتر مواقع با استفاده از عبارات زیر در تعاریف HttpURLConnection
کدتون، خطای recvfrom failed: ECONNRESET (Connection reset by peer)
برطرف خواهد شد:
System.setProperty("http.keepAlive", "false"); myHttpUrlConnection.setRequestProperty("connection", "close");
5- برای حل مشکل GC overhead limit exceeded در برنامه Eclipse کافیه ظرفیت حافظه Heap این برنامه رو در فایل eclipse.ini تغییر بدید:
-XX:MaxPermSize=1024m -Xms512m -Xmx1024m
6- نکته جزیی: آیا میدونید کال بک onCancel()
فقط توسط دستور cancel()
صدا زده میشه؟
7- با استفاده از تگ <include>
قادر خواهید بود از طراحی Layout های تکراری اجتناب کنید، و Layout های مشترک/تکراری رو re-use کنید!
8- فراموش نکنید که ViewHolder
خلاصه ترین و بهترین گزینه برای هندل کردن عناصر گرافیکی ListView
هستش.
9- آیا میدونید مقدار DEBUG
در فایل BuildConfig.java تنها زمانی false میشه که برنامه بصورت Signed Application Package کامپایل/export بشه؟
راه ساده برای اطلاع رسانی:
if (<MY-PACKAGE-NAME>.BuildConfig.DEBUG) { Log.wtf(LOG_TAG, "DEBUG-MODE IS ONE!"); }
نکته: این فایل Build.Config.java بصورت خودکار تولید و در مسیر /gen/<MY-PACKAGE-NAME>/BuildConfig.java
قرار داره.
10- جهت افزایش سرعت برنامه Android Studio میتونید:
1- پلاگین های بلااستفاده رو از مسیر File -> Settings -> Plugins غیرفعال کنید:
Android Games
Copyright
CVS Integeration
Mercurial integration
hg4idea
Subversion integration
Task management
2- از منوی File حالت PowerSaving برنامه Android Studio رو فعال کنید.
3- یک درایو SSD خریداری کنید!
11- آیا میدونید در HttpURLConnection
باید redirect ها رو بصورت دستی هندل کنید؟
به این صورت که ابتدا کد header ارسال شده از طرف سرور رو توسط getResponseCode
بررسی می کنید، اگر با HTTP_MOVED_TEMP
یا HTTP_MOVED_PERM
یا HTTP_SEE_OTHER
برابر بود، توسط getHeaderField
محتوای فیلد Location و Set-Cookie رو بازیابی می کنید و مجدداً درخواست دیگه ای با URL جدید بهمراه کوکی ارسال می کنید.
12- آیا می دونید هنگامی که دستگاه با وضعیت low internal storage space مواجه میشه، اندروید بصورت خودکار cache برنامه ها رو(بدون اطلاع رسانی) پاک میکنه؟
13- (بطور پیشفرض) اگر برنامه ای رو از طریق صفحه Home باز کنید، اکتیویتی Main برنامه بازمیشه، درصورتی که اگر همون برنامه رو از طریق صفحه Recent apps باز کنید، آخرین اکتیویتی که درش حضور داشتید باز میشه. (در اندروید 2 به بعد)
14- نکته جزیی برای API 17 به قبل: به دلایل امنیتی، گوگل پیشنهاد کرده که در حین کار با دستور getSharedPreferences
، از حالت MODE_PRIVATE
استفاده کنید.
MODE_PRIVATE: File creation mode: the default mode, where the created file can only be accessed by the calling application (or all applications sharing the same user ID).
نکته: این فایل preference بطور پیشفرض در مسیر /data/data/<YOUR-PACKAGE-NAME>/shared_prefs/
دستگاه تون قرار داره.
15- نکته جزیی: SharedPreference
ها برای ذخیره تنظیمات برنامه هستند، و نه ذخیره data ی برنامه!
16- SharedPreferences.commit()
یا SharedPreferences.apply()
؟
apply: در اندروید 2.3 به بعد تعبیه شده، هیچ return ای بعد از انجام عملیات نداره(چه failure بشه چه success)، کمی سریعتر از commit هستش، داده ها رو بصورت asynchronously ذخیره میکنه(thread ش رو قفل نمی کنه)، اطلاعات رو سریعاً در RAM ثبت میکنه و بعد روی دیسک ذخیره میکنه و...
commit: در همه نسخ اندروید وجود داره، مقدار return ش نسبت به failure/success شدن boolean هستش، کمی کندتر از apply هستش، داده ها رو بصورت synchronously ذخیره میکنه(thread ش رو قفل می کنه)، اطلاعات رو مستقیماً برروی دیسک ذخیره میکنه و بهتره بکمک multi-threading طراحی بشه...
17- یک تابع پیشنهادی بهبود یافته برای استفاده از دستورات commit/apply
:
public static final void iCommit(final SharedPreferences.Editor editor) { if (Build.VERSION.SDK_INT >= 9) // Gingerbread { editor.apply(); } else { new Thread() { @Override public void run() { editor.commit(); } }.start(); } }
18- فراموش نکنید برای استفاده از اینترفیس OnSharedPreferenceChangeListener
و کال بک onSharedPreferenceChanged()
باید shared preferences رو در متد OnResume()
و OnPause()
ثبت کنید:
@Override protected final void onResume() { getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); super.onResume(); // Call at last. } @Override protected final void onPause() { getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); super.onPause(); // Call at last. }
19- دقت کنید که کاربرد و رفتار اینترفیس OnPreferenceChangeListener
با OnSharedPreferenceChangeListener
متفاوته!
اینترفیس OnPreferenceChangeListener
زمانی فعال میشه که تغییری در کلیدش صورت بگیره(یک کلید)، اما OnSharedPreferenceChangeListener
زمانی فعال میشه که تغییری در کل SharedPreference صورت بگیره... همچنین برای استفاده از کال بک OnPreferenceChangeListener
باید کلید رو توسط findPreference
ثبت کنید تا بتونه رویدادها رو شنود کنه.
20- در بیشتر مواقع دلیل رخداد اثتثنای NoClassDefFoundError android.os.AsyncTask باگیه که در Google Play Service وجود داره و بسادگی با روش زیر قابل حله:
try { Class.forName("android.os.AsyncTask"); // Fix AsyncTask bug. } catch (final ClassNotFoundException exception) { }
21- دیده شده در خیلی از برنامه ها برای قراردادن فضاهای Blank در layout برنامه، از عنصر TextView
یا حتی LinearLayout
استفاده شده! در صورتی که باید از عنصر <View>
یا <Space>
(برای API 14 به بعد) استفاده بشه، اون هم به این شکل:
برای اندروید های 2 به بعد <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> برای اندروید های 4 به بعد <Space android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/>
22- در بعضی موارد با اضافه کردن header های زیر در HttpClient
یا UrlConnection
تون، مشکل FileNotFoundException
رفع خواهد شد:
"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*" "User-Agent", "Mozilla/5.0 ( compatible ) "
23- آیا می دونید در try/finally بلوک finally همیشه اجرا میشه، بجز زمانی که System.exit صدا زده بشه یا VM بسته بشه یا StackOverflowException
پرتاب بشه؟
نکته: درصورتی که دستور System.exit استثنای SecurityException رو پرتاب کنه، بلوک finally اجرا خواهد شد.
24- در بعضی موارد با استفاده از getText().clear()
بجای setText("")
، خطای X on inactive InputConnection برطرف خواهد شد.
25- همچنین در بعضی موارد، با بستن Keyboard برنامه قبل از بستن شدن Fragment/Activity، خطای showStatusIcon on inactive InputConnection برطرف خواهد شد:
@Override protected void onPause() { super.onPause(); View _view = getCurrentFocus(); if (_view != null) { final InputMethodManager _imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); if (_imm != null) { _imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } _view.clearFocus(); _view.setFocusable(false); } }
26- در صورتی که از UrlConnection
برای POST استفاده می کنید و با خطای ProtocolException: content-length promised x bytes, but received 0 مواجه شدید(در اندروید 4 به بعد)، بدونید که نباید Content-Length رو خودتون تنظیم کنید و باید به عهده خود UrlConnection
بذارید تا تنظیمش کنه... پس اون خط رو حذف کنید.
27- برای اینکه کیبورد نرم افزاری، در حالت landscape تمام صفحه رو پوشش نده، باید:
- خاصیت android:windowSoftInputMode="adjustResize"
رو به تگ Activity فایل AndroidManifiest.xml اضافه کنید.
- یا خاصیت android:imeOptions="flagNoExtractUi"
رو به تگ EditText فایل layout اضافه کنید.
28- یک تابع پیشنهادی بهبود یافته برای استفاده از ClipboardManager
، سازگار با تمام نسخه های اندروید:
public static final void copyToClipboard(final Context context, final EditText edit_text) { final ClipboardManager _clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); if (_clipboardManager != null) { if (Build.VERSION.SDK_INT >= 3) // Honeycomb { final ClipData _clipData = ClipData.newPlainText(" ", edit_text.getText().toString()); _clipboardManager.setPrimaryClip(_clipData); } else { _clipboardManager.setText(edit_text.getText().toString()); } } }
29- نکته جزیی: فراموش نکنید که داده نوع NULL
همیشه یک مقدار Invalid/نامعتبر هستش و هرچیزی بجز NULL
یک مقدار Valid/معتبر هستش، حنی ""
30- نکاتی درباره متد toString()
و valueOf()
:
- متد valueOf در پشت پرده متده toString رو صدا می زنه.
- از نظر سرعت، متد toString کمی سریعتر از متد valueOf هستش.
- valueOf رو میشه گفت flexible تره و بازه دیتایی بیشتری رو قبول می کنه.
- اگر داده ورودی به این متد ها NULL باشه، متد toString استثنای NullPointerException پرتاب میکنه، در صورتی که متد valueOf رشته "null" رو برمیگردونه(null-safe هستش).
- valueOf یک متد static هستش، درصورتی که toString یک متد object.
31- یادتون باشه که تنها دلیل استفاده از ابزارهای اتوماسیون build(مثل gradle, maven, phing, ant) فقط کاهش خطاهای انسانی و صرفه جویی در زمان هستش.
32- از Java 6 به بعد(JDBC 4.0) دیگر نیازی به لود کردن درایور دیتابیس توسط دستور Class.forname
یا registerDriver
نیست، اینکار توسط JVM بصورت خودکار انجام میشه. (درصورت وجود فایل Driver)
33- همیشه اطلاعات ورودی/کاربر رو قبل از ثبت کردن در log، ابتدا فیلترسازی کنید!
34- هرگز از اعداد منفی برای تعیین Status/Exit code استفاده نکنید. از انجاییکه برای سیستم هر چیزی جز عدد 0 به FALSE
ترجمه میشه و بسیاری از زبانها قابلیت return
کردن اعداد منفی برای Status/Exit code رو ندارن، بهترین مقدار اعداد 0 یا مثبت هستن.
35- کاربردها و اهداف بلوک های static
:
- برای initialize کردن کدهای استاتیک(static) که هنگام Load شدن کلاس(توسط classloader) اعمال بشن
public static Map<String, String> myField = new HashMap<String, String>(); static { myField.put("Test name", "Test value"); // ... }
- برای initialize کردن کلاسهای master
public class MasterClass { static { SlaveClass.initialize(); // ... } }
- بارگذاری کتابخانه های Native
static { System.loadLibrary("TestLibrary"); }
توجه: باید فیلدهای static
در بلوک static
قرار بگیرند و initialize بشن و نه در constructor! اینها بخشی از class definition هستن و نه object.
36- نکاتی راجب الگوهای طراحی DAO و Repository:
هردو object-oriented هستن
هردو زیر مجموعه Integration Tier Design Pattern هستن
هردو در لایه DAL یا persistence layer قرار دارن و برای پیاده سازی این لایه ها استفاده میشن
هردو میتونن Object یا دسته ای از Objects رو return کنن
هردو میتونن برای دور نگه داشتن application از تکنولوژی زیرساختی data source استفاده بشن(در واقع یک uniform data access API)
DAO به data source نزدیکتره اما Repository به application نزدیکتره
از DAO بیشتر برای دسترسی به Entities استفاده میشه و از Repository بیشتر برای سرهم کردن چند کلاس/خروجی DAO
از DAO برای مخفی سازی مباحث سطح پایین data source و پیچیدگی ها استفاده میشه
DAO معمولاً به data source vendor خاصی وابسته نیست
DAO معمولاً table محور هست اما Repository معمولاً Object محور
37- نکاتی راجب الگوهای Dependency Injection, Service Locator, Inversion of Control:
- الگوی Dependency Inversion Principle (DIP) منتسب به تجزیه کردن کد هستش، به این صورت که کلاسهای سطح بالا نباید به قسمت های سطح پایینتر وابستگی مستقیم داشته باشه، بلکه باید توسط لایه abstract یا interface به سطوح پایینتر وابستگی داشته باشند.
- Dependency Injection یک الگو هست اما Container و Inversion of Control یک روش برای اجرای الگوی DI.
- توسط الگوی Inversion of Control قادرید dependency اشیا رو بعد از compile یا در محیط production هم تغییر بدید.
38- تفاوت Service Locator با الگوهای DI:
- Service Locator امکان resolve کردن dependency رو "از داخل کلاس" فراهم میکنه. اما DI امکان inject کردن dependency رو "از خارج کلاس" فراهم میکنه.
- همه dependency ها به Service Locator وابسته میشن(خود یک dependency هستش). اما DI فقط یکبار هنگام startup فراخوانی میشه.
- dependency در DI (نوع constructor) صریح و مشخص inject میشه اما در Service Locator اینطور نیست.
- خوانایی در الگوی Service Locator پایین تر از DI هستش.
39- نکته جزیی: در دنیای Java واژه Entity درواقع همون Model یا POJO هستش که به یک Table در دنیای database اشاره داره.
40- همیشه از language keywords(مثل int, string, float
) بجای base class type(مثل Integer, String, Double
) استفاده کنید.
مقالات مرتبط
نکات و اصول مهم در برنامه نویسی Java/Android
#2 - نکات و اصول مهم در برنامه نویسی Java/Android
#4 - نکات و اصول مهم در برنامه نویسی Java/Android
#5 - نکات و اصول مهم در برنامه نویسی Java/Android