Android开发与解决开发问题

文章目的


本文将讨论一般的Android开发问题。 我们都知道开发程序是一项艰巨的工作,需要花费大量时间和精力,有时找到一个问题的解决方案也需要很多时间,因为Internet上的某些解决方案并不总是有效。

本文将解决以下问题:

  • 适用于Android的自定义键盘
  • 多线程
  • 在程序中整合广告

适用于Android的自定义键盘


在我的程序中,在计算器中,我必须制作自己的键盘,因为从系统键盘输入数学公式非常不舒服。 为了解决这个问题,我爬了很多论坛,尝试了几种不同的解决方案,但是所有这些解决方案都没有达到预期的效果。

让我们开始:
  1. 在android studio中创建一个新项目。
  2. 让我们创建几个类
  3. 测试应用程序

让我们用9个字符组成一个简单的键盘,它可以删除这些字符。
让我们将项目命名为KeyBoardTest



选择一个空的活动并开始



完成后,我们创建了新项目。 现在我们将处理最基本的一个,即在文件夹中创建一个布局文件-res / layout并将其命名为Keyboard,在这里我们将拥有键盘的外观。

让我们画一下这个键盘:

<?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> 

绘制键盘后,我们可以创建一个类,该类将注册所有键击并编写所需的内容。 请注意,每个textview都有一个ID-这非常重要!

将此类称为KeyBoardListener。

我们编写类的构造函数,它以View作为参数—我们正在处理的字段,换句话说,就是editText的位置,它还接受editText本身,我们将在其中打印键盘上的字符。

 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); } } 

现在详细考虑此代码。 我们将editText和view传递给构造函数本身,以获取按钮并为其分配输入。 应当注意,删除按钮方法使用“语法糖”,换言之,它是缩写的代码输入。 并不是每个人都知道这种设计,所以我决定我们应该注意它。 这对于初学者尤其有用。

这种设计是这样工作的

 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类和insert方法的原因。
由于整个方法被称为一个单独的类,因此我们可以将其添加到任何地方,并在任何程序中使用它。 因此,获得了代码的客观性。

但是我没有向您展示如何使用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> 

现在,通过简单的操作,我们可以在任何地方使用键盘,甚至可以零碎使用。

在我们的应用程序中,键盘如下所示



多线程


多线程-名称暗示它有很多线程。 还有很多线程-这意味着要同时执行多个操作。 多线程是编程中一个非常有问题的话题。 在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中,然后将其传递给类的构造函数。 为了使一切正常工作,我们必须在editText之后将textView添加到我们在创建项目时拥有的activity_main中。

 <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中设置付款方式,否则广告将不会加载。 由于我没有设置帐户,我浪费了一整天,然后他们告诉我支持:“我设置帐户了吗?” 然后,我在2小时后出现了一个广告。

结论

由于本文是针对初学者的,所以我想指出一件事。 如果您真的喜欢编程,并且准备花费大量时间解决特定问题,那么编程就是您自己的了,否则就不用了。 另外,不要超越。 由于解决方案也太长,所以不太复杂也不是太简单的事情就不好了。 但这是显而易见的事实。 实际上,我在互联网上的某个地方读过这个短语。 实际上,这是真的。 如果您考虑一下,那么实际上,如果进行编程,认真的编程将是如此的容易,那么所有人中的一小部分将不会被它占用。

我希望我的文章对某人有用,并确实对某人有所帮助,它可以帮助我节省时间,因为我亲自杀死了键盘上的一个键盘,这看起来很简单,三天,花了我2​​个时间来获取线索并寻找正常的解决方案的一天。

Source: https://habr.com/ru/post/zh-CN426223/


All Articles