تطوير Android وحل مشكلات التطوير

الغرض من المقال


ستناقش هذه المقالة مشاكل تطوير Android وتطويره بشكل عام. نعلم جميعًا أن تطوير برنامج يتطلب الكثير من العمل الشاق ، والذي يستغرق الكثير من الوقت والجهد ، وأحيانًا يستغرق الكثير من الوقت لإيجاد حل لمشكلة ، لأن بعض الحلول من الإنترنت لا تعمل دائمًا.

تتناول هذه المقالة المشكلات التالية:

  • لوحة مفاتيح مخصصة لنظام Android
  • تعدد
  • دمج الإعلان في البرنامج

لوحة مفاتيح مخصصة لنظام Android


في برنامجي ، اضطررت إلى إنشاء لوحة المفاتيح الخاصة بي ، لأن إدخال الصيغ الرياضية من لوحة مفاتيح النظام أمر غير مريح للغاية. في محاولة لحل هذه المشكلة ، تسلقت مجموعة من المنتديات ، وجربت العديد من الحلول المختلفة ، لكن جميعها لم تعط النتيجة المرجوة.

لنبدأ:
  1. إنشاء مشروع جديد في android studio.
  2. لنقم بإنشاء فئتين
  3. اختبار التطبيق

لنقم بإنشاء لوحة مفاتيح بسيطة مكونة من 9 أحرف مع إمكانية حذف هذه الأحرف.
دعونا نسمي مشروعنا KeyBoardTest



اختر نشاطًا فارغًا وابدأ



تم ، لقد أنشأنا مشروعنا الجديد. الآن سنتعامل مع أبسطها ، وهو إنشاء ملف تخطيط في المجلد - res / layout ونسميه لوحة المفاتيح ، هنا سيكون لدينا مظهر لوحة المفاتيح.

لنرسم لوحة المفاتيح هذه:

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_gravity="bottom" android:background="@color/colorBlue" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <TextView android:id="@+id/one" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/one" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/two" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/two" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/three" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/three" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/four" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/four" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/five" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/five" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <TextView android:id="@+id/six" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/six" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/seven" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/seven" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/eight" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/eight" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/nine" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/nine" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> <TextView android:id="@+id/delete" android:textColor="@color/colorWhite" android:gravity="center" android:textSize="30sp" android:text="@string/delete" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"/> </LinearLayout> </LinearLayout> </FrameLayout> 

بعد رسم لوحة المفاتيح الخاصة بنا ، يمكننا إنشاء فصل لتسجيل جميع ضغطات المفاتيح الخاصة بنا وكتابة ما نحتاج إليه. يرجى ملاحظة أن كل عرض نصي له معرف - وهذا مهم جدًا!

استدعاء هذه الفئة KeyBoardListener.

نكتب مُنشئ صفنا ، ويأخذ الأمر "عرض كحجة" - الحقل الذي نعمل فيه ، وبعبارة أخرى ، موقع نص التحرير لدينا ، كما أنه يأخذ تحرير النص نفسه ، والذي سنطبع فيه الأحرف من لوحة المفاتيح الخاصة بنا.

 package keyboard.develop.keyboardtest; import android.view.View; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; public class KeyBoardListener { EditText editText; private StringBuilder finalText = new StringBuilder(); KeyBoardListener(View view, final EditText editText) { this.editText = editText; TextView one = view.findViewById(R.id.one); TextView two = view.findViewById(R.id.two); TextView three = view.findViewById(R.id.three); TextView four = view.findViewById(R.id.four); final TextView five = view.findViewById(R.id.five); TextView six = view.findViewById(R.id.six); TextView seven = view.findViewById(R.id.seven); TextView eight = view.findViewById(R.id.eight); TextView nine = view.findViewById(R.id.nine); TextView delete = view.findViewById(R.id.delete); final LinearLayout layout = view.findViewById(R.id.keyBoard); one.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "1"); setTextSelection(); } }); two.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "2"); setTextSelection(); } }); three.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "3"); setTextSelection(); } }); four.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "4"); setTextSelection(); } }); five.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "5"); setTextSelection(); } }); six.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "6"); setTextSelection(); } }); seven.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "7"); setTextSelection(); } }); eight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "8"); setTextSelection(); } }); nine.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); finalText.insert(selection, "9"); setTextSelection(); } }); delete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int selection = editText.getSelectionEnd(); if (finalText.length() > 0) { finalText = stringToBuilder(finalText.substring(0, selection - 1 == -1 ? 0 : selection - 1) + finalText.substring(selection)); editText.setText(finalText); } editText.setSelection(selection - 1 <= 0 ? 0 : selection - 1); } }); editText.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { layout.setVisibility(View.VISIBLE); } }); } private StringBuilder stringToBuilder(String s) { return new StringBuilder(s); } private void setTextSelection() { int selection = editText.getSelectionEnd(); editText.setText(finalText); editText.setSelection(selection + 1); } } 

الآن فكر في هذا الرمز بالتفصيل. قمنا بتمرير تحرير النص وعرضه للمنشئ نفسه من أجل أخذ الأزرار وتعيين المدخلات. وتجدر الإشارة إلى أن طريقة زر الحذف تستخدم "السكر النحوي" ، وبعبارة أخرى ، فهي عبارة عن إدخال رمز مختصر. لا يعرف الجميع هذا التصميم ، لذلك قررت أنه يجب علينا الانتباه إليه. يمكن أن يكون هذا مفيدًا بشكل خاص للمبتدئين.

هذا التصميم يعمل بهذه الطريقة

 int p = () ?  1 :  2; int p = k == 2 ? 7 : 3; //      if (k == 2) p = 7; else p = 3; 

لكننا ابتعدنا عن الموضوع. الآن ، بعد أن أصبح مُنشئنا جاهزًا ، ويمكننا الرد على نقرات الأزرار ، يمكننا استخدام فصلنا. نحتاج أولاً إلى استدعاء هذا الفصل في نشاطنا الرئيسي

 package keyboard.develop.keyboardtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.View; import android.view.WindowManager; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private LinearLayout layout; private ExecutorThread executorThread; @Override protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); //   ,     super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final EditText editText = findViewById(R.id.edit); layout = findViewById(R.id.keyBoard); new KeyBoardListener(layout, editText); executorThread = new ExecutorThread((TextView)findViewById(R.id.textView)); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void afterTextChanged(Editable editable) { if (!editable.toString().equals("")) { executorThread.setK(Integer.parseInt(editText.getText().toString())); executorThread.doWork(); } } }); } @Override public void onBackPressed() { layout.setVisibility(View.GONE); //   } } 

يجدر الانتباه إلى هذا الخط.

 getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 

في هذا السطر ، نوقف تشغيل لوحة مفاتيح النظام ، ولكن في نفس الوقت نترك المؤشر حتى نتمكن من التنقل بين الأحرف وإدراج أرقام / أحرف ، وما إلى ذلك. هذا هو بالضبط سبب استخدامنا لفئة StringBuilder وطريقة الإدراج في الكود أعلاه.
نظرًا لحقيقة أن هذه الطريقة بأكملها تسمى فئة منفصلة ، يمكننا إضافتها في أي مكان واستخدامها في أي برامج. وبالتالي ، يتم الحصول على موضوعية الشفرة.

لكنني لم أريكم كيفية القيام بذلك في كود xml ، وكيف تخبرنا عن موقع لوحة المفاتيح هذه ، وكل شيء بسيط للغاية

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="keyboard.develop.keyboardtest.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:textColor="@color/colorPrimary" android:gravity="center" android:textSize="25sp" android:layout_width="match_parent" android:layout_height="50dp" android:text="Write your text here!"/> <EditText android:id="@+id/edit" android:layout_width="match_parent" android:layout_height="50dp"/> </LinearLayout> <LinearLayout //       android:visibility="gone" android:id="@+id/keyBoard" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_gravity="bottom"> <include layout="@layout/keyboard"/> //   ,    </LinearLayout> </FrameLayout> 

الآن من خلال التلاعب السهل ، يمكننا استخدام لوحات المفاتيح الخاصة بنا في أي مكان ، حتى في الأجزاء.

في تطبيقنا ، تبدو لوحة المفاتيح على هذا النحو



تعدد


Multithreading - يشير الاسم إلى أنه يحتوي على الكثير من الخيوط. الكثير من الخيوط - وهذا يعني إجراء عدة عمليات في نفس الوقت. تعد خاصية Multithreading موضوعًا معقدًا جدًا في البرمجة. ماذا في لغة C ++ ، وما في لغة Java ، وما هي اللغات الأخرى ذات مؤشرات الترابط المتعددة التي كانت تواجه دائمًا مشاكل. لحسن الحظ ، تحتوي جميع اللغات تقريبًا على حل عالي المستوى لهذه المشكلة. لكننا نطور حاليًا لنظام Android ، لذلك سنتحدث عن Anroid ، وبشكل أكثر تحديدًا عن لغة برمجة Java.

في Java YP يوجد شيء مثل Thread - إنه ملائم للرسم ، مع إعادة رسم الصورة بشكل متكرر ، هناك العديد من المقالات حول هذا الموضوع ، بما في ذلك Habré ، لذلك لن أفكر في هذا الخيار. أنا مهتم بما يسمى "تيار النوم" ، وهو تيار ينتظر دعوته لحل مهمة معينة. هذه هي الحالة عندما قمت باستدعاء خيط ، عملت ونمت ، دون إضاعة موارد الجهاز أثناء انتظار مهمة جديدة.

واسم ما وصفته أعلاه هو فئة من الحزمة القياسية java.util.concurrent ExecutorServise

جوهر هذه الفئة هو أنه يمكن إعادة استخدام نفس الخيط دون إنشاء خيط جديد. والآن سننظر في كيفية عملها ، ولن ننشئ برنامجًا جديدًا ، ولكننا سنواصل العمل في برنامجنا.

للقيام بذلك ، قم بإنشاء فئة جديدة ، والتي سوف تسمى ExecutorThread. نطرح المشكلة التي نحتاجها لإضافة واحد إلى الرقم p حتى يساوي هذا p العدد الذي قدمناه في 4 درجات. يتم عمل كل شيء بحيث يكون الحساب أطول. وحتى لا تتجمد الواجهة بأكملها ، سنضع كل شيء في سلسلة محادثات منفصلة.

 package keyboard.develop.keyboardtest; import android.widget.TextView; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorThread { private ExecutorService executorService; private Thread thread; private int p = 0; private int pow = 0; private int k = 0; private TextView textView; ExecutorThread(final TextView text) { p = 0; textView = text; thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < pow; i++) p++; String s = "Result " + k + "^4 = " + String.valueOf(p); textView.setText(s); } }); thread.start(); executorService = Executors.newSingleThreadExecutor(); } void doWork() { executorService.submit(thread); } void setK(int k) { p = 0; this.k = k; pow = (int) Math.pow(k, 4); textView.setText("Please wait. We are calcing!"); } } 

كما نرى ، في تلك اللحظة ، بينما لم نحسب بعد ، نرى الإدخال "الرجاء الانتظار. نحن نحسب! "، وهو أمر واضح -" الرجاء الانتظار. نحن نحسب! " وبعد العد ، سنقوم بإخراج النص إلى textView ، الذي مررناه إلى مُنشئ صفنا. لكي يعمل كل شيء ، يجب أن نضيف textView بعد نص التحرير الخاص بنا إلى نشاطنا الرئيسي ، الذي كان لدينا عند إنشاء المشروع.

 <TextView android:gravity="center" android:textColor="@color/colorPrimary" android:textSize="25sp" android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="50dp"/> 

ونحتاج أيضًا إلى إضافة الرمز أدناه إلى فصلنا الرئيسي - MainActivity.

 executorThread = new ExecutorThread((TextView)findViewById(R.id.textView)); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {} @Override public void afterTextChanged(Editable editable) { if (!editable.toString().equals("")) { executorThread.setK(Integer.parseInt(editText.getText().toString())); executorThread.doWork(); } } }); 

تجدر الإشارة إلى أن طريقة addTextChangeListener هي المسؤولة عن تغيير النص في editText. كما نرى ، داخل الطريقة ، نسمي وظيفة doWork () ، والتي بدورها تنفذ هذه الخطوط

 executorService.submit(thread); 


لقد تحققت من كل ما سبق على هاتفي ، لذلك إذا فعلت كل شيء بشكل صحيح ، فلا يجب أن تواجه مشاكل أو أخطاء.

كما نرى ، هذه الطريقة مريحة وسهلة الفهم ، حاولت وصف كل شيء بسيط قدر الإمكان ، لذلك آمل أن يكون كل شيء واضحًا لك ، لكنني لم أفتقد أي شيء.

والآن ، دعنا ننتقل إلى النقطة 3 من مقالتنا ، وهي تكامل الإعلانات.

تكامل الإعلان


في الواقع ، لا يمكنني التحدث كثيرًا عن هذا ، يمكنني تقديم المشورة فقط. مع الإعلان ، ليس كل شيء سهل وشفاف. أنا شخصياً أنصحك باستخدام Appodeal ، فقد كان في السوق منذ وقت ليس ببعيد ، ولكنه يعمل بنجاح كبير.

تجدر الإشارة أيضًا إلى وجود دعم جيد جدًا باللغة الروسية ، والذي يجيب دائمًا على سؤالك أو مشكلتك على الفور. وهذا يوضح على الفور مدى ولاء هذه الشبكة.

أريد أن أقول على الفور ، إذا كنت تستخدمه فجأة ، فتأكد من إعداد الدفع في AdMob و Appodeal ، وإلا فلن يتم تحميل الإعلان. نظرًا لأنني لم أقوم بإعداد حسابات ، فقد أضعت اليوم كله ، ثم أخبروني في دعمهم: "هل قمت بإعداد حسابات؟" وبعد أن فعلت ذلك ، ظهر إعلان بعد ساعتين.

الخلاصة

نظرًا لأن هذه المقالة مخصصة للمبرمجين المبتدئين ، أود أن أشير إلى شيء واحد واضح. إذا كنت تحب البرمجة حقًا ، وكنت على استعداد لقضاء أطنان من الساعات في حل مشكلة معينة ، فإن البرمجة هي لك ، وإلا فلا. أيضا ، لا تتجاوز. نظرًا لأن الحل طويل جدًا أيضًا ، فإن شيئًا ليس معقدًا للغاية وليس بسيطًا جدًا ليس جيدًا. لكن هذه حقيقة واضحة. في الواقع ، قرأت هذه العبارة في مكان ما على الإنترنت. في الحقيقة هذا صحيح إذا فكرت في الأمر ، فعندئذ حقًا ، إذا كانت البرمجة ، فإن البرمجة الجادة ستكون سهلة للغاية ، فلن يكون جزءًا صغيرًا من الأشخاص من العدد الإجمالي لجميع الناس مشغولين بها.

آمل أن تكون مقالتي مفيدة لشخص ما وقد ساعدت شخصًا ما حقًا ، فقد ساعدتني في توفير الوقت ، لأنني شخصياً قتلت مثل هذا الشيء البسيط على لوحة المفاتيح ، بدا الأمر وكأنه 3 أيام ، واستغرق الأمر يومين للبحث والبحث عن حل عادي اليوم.

Source: https://habr.com/ru/post/ar426223/


All Articles