How to implement dependency inversion Principle [duplicate]

This question already has an answer here:

  • C# classes for adding form components dynamically 1 answer

I’m reading on how to implement design patterns. I’m trying to implement the DIP after reading SOLID principles. I’m a beginner in design patterns.

Application scope:

I’m building a Windows form C# project that keeps some information. It will create a bunch of textboxes and comboboxes dynamically, depend upon user input.

In this application, I created multiple class where all the class will have the same behavior. So I thought of creating a abstract class called Component .

All the subclass which is also a form of component will have a is-a relationship with the main class.

On whenever I create a new dynamic component I can just inherit the add_components class so that the new class will implement the add_dynamic_components methods.

public abstract class add_components {     public abstract void add_dynamic_components(int noOfComponets, int locationX, int locationY, Form1 l, int currentTabIndex); }  public class addDynamicCptboxComponents : add_components {     public override void add_dynamic_components(int getNoOfTxtBox, int pointX, int pointY, Form1 f, int currentTabIndex)     {         TextBox txtBox = new TextBox();         f.panel1.Controls.Add(txtBox);         txtBox.Location = new Point(pointX, pointY);         txtBox.Size = new System.Drawing.Size(75, 23);         f.panel1.Controls.Add(txtBox);         txtBox.Name = "Add_txtBox" + getNoOfTxtBox;         txtBox.TabIndex = currentTabIndex * 7 + 2;     } }  public class addDynamicDateofServiceComponents : add_components {      public override void add_dynamic_components(int getNoOfTxtBox, int pointX, int pointY, Form1 f, int currentTabIndex)     {         TextBox txtBox = new TextBox();         f.panel1.Controls.Add(txtBox);         txtBox.Location = new Point(pointX, pointY);         txtBox.Size = new System.Drawing.Size(75, 23);         f.panel1.Controls.Add(txtBox);         txtBox.Name = "Add_dos_txtBox" + getNoOfTxtBox;         txtBox.TabIndex = currentTabIndex * 7 + 1;     } } public class addDynamicSpellboxComponents : add_components {      public override void add_dynamic_components(int getNoOfSpellTxtBox, int spPointX, int spPointY, Form1 f, int currentTabIndex)     {         RichTextBox sp = new RichTextBox();         f.panel1.Controls.Add(sp);         sp.Location = new Point(spPointX, spPointY);         sp.Size = new System.Drawing.Size(230, 43);         f.panel1.Controls.Add(sp);         sp.Name = "RichTextbox" + getNoOfSpellTxtBox;         sp.TabIndex = currentTabIndex * 7 + 3;      } } 

On implementation I found that my form class is tightly coupled with the lower class.

Implementation:

    public partial class Form1 : Form     {         addDynamicCptboxComponents addcomponent = new addDynamicCptboxComponents();         addDynamicSpellboxComponents addSpellboxComponent = new addDynamicSpellboxComponents();         addDynamicDateofServiceComponents adddoscomponents = new addDynamicDateofServiceComponents();          public Form1()         {             try             {                 InitializeComponent();             }             catch (Exception ex)             {                 //Write ex.Message to a file                 using (StreamWriter outfile = new StreamWriter(@".\error.txt"))                 {                     outfile.Write(ex.Message.ToString());                 }             }             initalizeUserdefinedComponents();          }          public void createDynamiccomponents()         { int padding = 24; int gap = 50;             int value;             if (int.TryParse(txtboxvalLines.Text, out value))             {                 int txtno = int.Parse(txtboxvalLines.Text);                 int pointX = 125;                 int pointY = padding ;                 int spPointX = 240;                 int spPointY = padding ;                 int txtboxRecommendedpointX = 640;                 int txtboxRecommendedpointY = padding ;                 int btnPointX = 1170;                 int btnPointY = padding ;                 int cmbPointX = 520;                 int cmbPointY = padding ;                 int pncPointX = 920;                 int pncPointY = padding ;                 int finalcmbPointX = 780;                 int finalcmbPointY = padding ;                 int DOSPointX = 35;                 int DOSPointY = padding ;                  for (int i = 0; i < txtno; i++)                 {                     customize_panel();                      addcomponent.add_dynamic_components(i, pointX, pointY, this, i);                     addSpellboxComponent.add_dynamic_components(i, spPointX, spPointY, this, i);                      adddoscomponents.add_dynamic_components(i, DOSPointX, DOSPointY, this, i);                     panel1.Show();                     spPointY += gap;                     btnPointY += gap;                     cmbPointY += gap;                     pointY += gap;                     pncPointY += gap;                     txtboxRecommendedpointY += gap;                     finalcmbPointY += gap;                     DOSPointY += gap;                 }                  btnAdd.Enabled = false;                 txtboxvalLines.Enabled = false;                 panel1.Focus();             }             else             {                 MessageBox.Show("Please provide the count of total Claim lines");                 txtboxvalLines.Text = "";             }         }     } 

In the above case you can see that the form is tightly coupled with the lower class i.e. addDynamicCptboxComponents, addDynamicSpellboxComponents which is seems to be a violation of DIP as far what i learned in internet.

Now my questions is:

  1. Whether my application violates DIP ? – I believe so. If yes In my case how to implement DIP in the above case. I have never used one.

C# ClientWebSocket implementation

I’m working on implementing websockets in my current project in C#. Could anyone please give me some pointers/suggestions for what could be improved? Specifically, I’m most unsure about how to actually use this class in my main code. I can’t figure out when/how I would use UsableWebsocket.Send() though!

Thanks in advance!

public class UsableWebsocket {     public int BufferSize = 512;     public bool IsVerbose = false;      public event Action<string> OnReceiveMessage = delegate { };      private ClientWebSocket socket;     private readonly UTF8Encoding encoder = new UTF8Encoding();     private readonly object consoleLock = new object();      public UsableWebsocket(int bufferSize = 512, bool isVerbose = false)     {         BufferSize = bufferSize;         IsVerbose = isVerbose;     }      public async Task ConnectTo(string uri)     {         socket = null;         try         {             socket = new ClientWebSocket();             await socket.ConnectAsync(new Uri(uri), CancellationToken.None);             lock (consoleLock)             {                 Console.ForegroundColor = ConsoleColor.Red;                 Console.WriteLine("WebSocket connected.");                 Console.ResetColor();             }         }         catch (Exception ex)         {             Console.WriteLine($  "Exception: {ex}");         }         finally         {             if (socket != null)                 socket.Dispose();             Console.WriteLine();              lock (consoleLock)             {                 Console.ForegroundColor = ConsoleColor.Red;                 Console.WriteLine("WebSocket closed.");                 Console.ResetColor();             }         }     }      public async Task Send(string message)     {         byte[] buffer = encoder.GetBytes(message);         await socket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);                 }      public async Task Listen()     {          while (socket.State == WebSocketState.Open)         {             var buffer = new ArraySegment<byte>(new byte[BufferSize]);             WebSocketReceiveResult result = null;              using (var ms = new MemoryStream())             {                 do                 {                     result = await socket.ReceiveAsync(buffer, CancellationToken.None);                     ms.Write(buffer.Array, buffer.Offset, result.Count);                 }                 while (!result.EndOfMessage);                  ms.Seek(0, SeekOrigin.Begin);                  if (result.MessageType == WebSocketMessageType.Text)                 {                     using (var reader = new StreamReader(ms, Encoding.UTF8))                     {                         var mess = reader.ReadToEnd();                         OnReceiveMessage(mess);                         if (IsVerbose)                         {                             LogStatus(mess);                         }                     }                 }             }          }     }      private void LogStatus(string message)     {         lock (consoleLock)         {             DateTime now = DateTime.UtcNow;             Console.ForegroundColor = ConsoleColor.Green;             Console.WriteLine($  "[{now.Hour:00}:{now.Minute:00}:{now.Second:00}] {message}");             Console.ResetColor();         }     }         } 

And the usage would be something like:

static void Main(string[] args)     {         new Thread( async () =>         {             Thread.CurrentThread.IsBackground = true;             socket = new UsableWebsocket();             socket.OnReceiveMessage += BitmexApi.ParseMessage;             await socket.ConnectTo(wsurl);             socket.Listen();         }).Start();          // do other things as necessary     } 

Google and the defamation/ fake reporting websites question.

Curious, if anyone is the know. For fifteen years or so Google has given great seo page 1 results to many of the big defamation/ extortion (complaint) websites. In the era of fake news, does anyone know why they continue to do this? Thousands of the pages on these sites are fake obvious erroneous reporting yet they continue to get great page one results. Will this just continue on indefinitely?

App that sets configuration data seems to be very inefficiently programmed

I’ve been writing my code like this for a really long time now, I am wondering if there is a more efficient way to do this. This is especially after a senior developer said my code was very amateurish.

App Purpose: I need to set some data for new employees when they join our organisation. This is a simple command app written in .net that takes an argument, splits it and then assigns the variables. A command might look like this: Setdata.exe -Marcus -true -true -false -false. The output is a file that we install on one of our sql servers.

The example below is a small one, but it is not common for the settings to hit 40-50 lines.

Code:

  internal static void ExportSolution(SqlService service, string parms)     {         try         {             parms = parms.Replace(" ", "");             string[] args = parms.Split('-');              string solutionName = args[1];             bool managed = Convert.ToBoolean(args[2]);             bool prefix= Convert.ToBoolean(args[3]);             bool profile= Convert.ToBoolean(args[4]);             bool email= Convert.ToBoolean(args[5]);             bool calendar= Convert.ToBoolean(args[6]);             bool appSettings= Convert.ToBoolean(args[7]);               AppSettingsRequestAppSettingsRequest= new AppSettingsRequest();              AppSettingsRequest.SolutionName = solutionName;              AppSettingsRequest.Managed = (managed == true) ? true : false;              AppSettingsRequest.prefix= (prefix== true) ? true : false;              AppSettingsRequest.Managed profile= (profile== true) ? true : false;              AppSettingsRequest.email= (email== true) ? true : false;              AppSettingsRequest.calendar= (calendar== true) ? true : false;              AppSettingsRequest.appSettings= (appSettings== true) ? true : false;               byte[] exportXml = exportSolutionResponse.ExportSolutionFile;             string filename = solutionName + ".zip";             File.WriteAllBytes(filename, exportXml);              Console.WriteLine("Solution exported to {0}.", filename);         }         catch (Exception ex)         {             Console.WriteLine(ex);         } 

Initial thoughts are that I could create a new class and then instantiate a new object with these variables, but is there anything to gain from doing this?

Python Turtle Pong Game

Im trying to add a start function to my code where the space key can be pressed to start my code as well as and end game where the first player to reach 5 wins. Please help

import turtle import random  screen = turtle.Screen() screen.title("Turtle Pong by Kyle Bonem") screen.bgcolor("blue") screen.setup(width=800, height=600) screen.tracer(0)  # Score score_1 = 0 score_2 = 0  # Ball Start ballX = 0 ballY = 0  # Player 1 player1 = turtle.Turtle() player1.speed("fastest") player1.shape("square") player1.shapesize(stretch_wid=4, stretch_len=1) player1.color("white") player1.penup() player1.goto(-350, 0)  # Player 2 player2 = turtle.Turtle() player2.speed("fastest") player2.shape("square") player2.shapesize(stretch_wid=4, stretch_len=1) player2.color("white") player2.penup() player2.goto(350, 0)  # Ball ball = turtle.Turtle() ball.speed("fastest") ball.shape("turtle") ball.color("green") ball.penup() ball.goto(ballX, ballY) ball.dx = 5 ball.dy = random.randint(4, 6)  # Scoreboard scoreboard = turtle.Turtle() scoreboard.speed(0) scoreboard.color("white") scoreboard.penup() scoreboard.hideturtle() scoreboard.goto(0, 260) scoreboard.write("Player 1: 0       Player 2: 0", align = "center",  font = ("Impact", 24, "normal"))  # Functions def player1_up():     y = player1.ycor()     y += 60     player1.sety(y)  def player1_down():     y = player1.ycor()     y -= 60     player1.sety(y)  def player2_up():     y = player2.ycor()     y += 60     player2.sety(y)  def player2_down():     y = player2.ycor()     y -= 60     player2.sety(y)  # Keyboard binding screen.listen() screen.onkeypress(player1_up, "w") screen.onkeypress(player1_down, "s") screen.onkeypress(player2_up, "Up") screen.onkeypress(player2_down, "Down")  # Main game loop while True:     screen.update()  # Moving the ball ball.setx(ball.xcor() + ball.dx) ball.sety(ball.ycor() + ball.dy)  # Border if ball.ycor() > 290:     ball.sety(290)     ball.dy *= -1  if ball.ycor() < -290:     ball.sety(-290)     ball.dy *= -1  if ball.xcor() > 390:     ball.goto(0, 0)     ball.dx *= -1     score_1 += 1     scoreboard.clear()     scoreboard.write("Player 1: {}       Player 2: {}".format(score_1, score_2), align = "center", font = ("Impact", 24, "normal"))  if ball.xcor() < -390:     ball.goto(0, 0)     ball.dx *= -1     score_2 += 1     scoreboard.clear()     scoreboard.write("Player 1: {}       Player 2: {}".format(score_1, score_2), align = "center", font = ("Impact", 24, "normal"))  # Bounce if (ball.xcor() > 335 and ball.xcor() < 350) and (ball.ycor() < player2.ycor() + 50 and ball.ycor() > player2.ycor() - 50):     ball.setx(335)     ball.dx *= -1  if (ball.xcor() < -335 and ball.xcor() > -350) and (ball.ycor() < player1.ycor() + 50 and ball.ycor() > player1.ycor() - 50):     ball.setx(-335)     ball.dx *= -1 

Unable to locate the code that Google Webmaster is finding

Google is showing the meta description we have loaded in squarespace. Bing is pulling in random numbers. Upon investigating the markup/structured data testing tool, I found the random string of numbers/text. But I’m having a hard time locating where I can update that information. The coding is not showing up in any of the homepage code injection sections of our squarespace site.

I used my MozBar and it looks like the site has “Open Graph Protocol” and “Twitter Cards”. In the Twitter Cards,…

Unable to locate the code that Google Webmaster is finding

Finding numbers where the nth power of the sum of the digits of the number is equal to the number itself

The title explains the code but I’ll give examples.

The number 81 fits the code because 8+1=9 and 92 =81.

The number 512 fits the code because 5+1+2=8 and 83 =512.

The number 17576 fits because 1+7+5+7+6=26 and 263 =17576.

The power of the sum of the digits can be any positive number.

My code is below but it is extremely inefficient in performance. I need the variable c to reach 25 but I haven’t seen past 16.

    public static int c = 0;     public static void TryAll(long x, long y)     {         for (int i = 2; i < 10; i++)         {             double powered = Math.Pow(y, i);             if (x % y == 0 && powered == x && x % 10 != 0)             {                 c++;                 Console.WriteLine("----- {0}", c);                 Console.WriteLine(powered);                 Console.WriteLine(y);                 Console.WriteLine(i);             }         }     }     public static void Main(string[] args)     {         int baseNum = 0;         for (c = c; c < 26; baseNum++)         {              if (baseNum > 9)             {                 int sum = 0;                 int baseNumD = baseNum;                 while (baseNumD != 0)                 {                     sum += baseNumD % 10;                     baseNumD /= 10;                 }                 TryAll(baseNum, sum);             }         }     } 

App crashes on First Open only when AdMob is added but working fine on next open

My App is working fine and then I tried to add AdMob dependencies. That’s when things get complicated. On first install and then open App crashes. But on second and consecutive open the app is working fine, all ads are showing.

For me, this is a bad user experience because at first open they think it is not a good app. And maybe they will uninstall it immediately.

Maybe there’s something I need to improve or add but I can’t figure it out. I need help regarding polishing my code.

Android Manifest

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"     package="com.gumangan.uecfispiritualhymns">      <uses-permission android:name="android.permission.INTERNET" />      <application         android:allowBackup="true"         android:icon="@mipmap/ic_launcher"         android:label="@string/app_name"         android:roundIcon="@mipmap/ic_launcher_round"         android:supportsRtl="true"         android:theme="@style/AppTheme">          <!-- TODO: Change android:value when final building  -->         <!--Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713-->         <meta-data             android:name="com.google.android.gms.ads.APPLICATION_ID"             android:value="ca-app-pub-3940256099942544~3347511713"/>          <activity             android:name="com.gumangan.uecfispiritualhymns.DictionaryActivity"             android:label="@string/app_name"             android:launchMode="singleTop"             android:theme="@style/AppTheme.NoActionBar">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                  <category android:name="android.intent.category.LAUNCHER" />                  <action android:name="android.intent.action.SEARCH" />             </intent-filter>              <meta-data                 android:name="android.app.searchable"                 android:resource="@xml/searchable" />         </activity>         <activity android:name="com.gumangan.uecfispiritualhymns.WordDetailActivity"             android:parentActivityName="com.gumangan.uecfispiritualhymns.DictionaryActivity">             <meta-data                 android:name="android.support.PARENT_ACTIVITY"                 android:value="com.gumangan.uecfispiritualhymns.DictionaryActivity"/>         </activity>     </application> 

Gradle Properties

// Top-level build file where you can add configuration options common to all sub-projects/modules.  buildscript { ext.kotlin_version = '1.3.10' repositories {     google()     jcenter() } dependencies {     classpath 'com.android.tools.build:gradle:3.2.1'     classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$  kotlin_version"      // NOTE: Do not place your application dependencies here; they belong     // in the individual module build.gradle files } }  allprojects { repositories {     google()     jcenter()     maven {         url "https://maven.google.com"     } } }  task clean(type: Delete) { delete rootProject.buildDir } 

Gradle Dependencies

apply plugin: 'com.android.application'  apply plugin: 'kotlin-android'  apply plugin: 'kotlin-android-extensions'  android { compileSdkVersion 27 defaultConfig {     applicationId "com.gumangan.uecfispiritualhymns"     minSdkVersion 16     targetSdkVersion 27     versionCode 1     versionName "1.0"     testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes {     release {         minifyEnabled false         proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'     } } }  dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$  kotlin_version" implementation 'com.android.support:appcompat-v7:27.1.1' implementation 'com.android.support:support-v4:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:cardview-v7:27.1.1' implementation 'com.android.support:customtabs:27.1.1'  implementation 'com.google.android.gms:play-services-ads:17.1.2'  testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } 

DatabaseHelper

package com.gumangan.uecfispiritualhymns  import android.content.Context import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper import android.preference.PreferenceManager  import java.io.FileOutputStream import java.io.IOException import java.io.InputStream import java.io.OutputStream  class DatabaseHelper(private var mContext: Context) : SQLiteOpenHelper(mContext, DATABASE_NAME, null, DATABASE_VERSION) { companion object {     private val DATABASE_NAME = "simple_dict.db"     private val DATABASE_VERSION = 1     val DB_CREATED = "DB_CREATED" }  private var mCreateDb = false private var mUpgradeDb = false  private fun copyDatabaseFromAssets(db: SQLiteDatabase?) {     var inputStream: InputStream? = null     var outputStream: OutputStream? = null      try {         inputStream = mContext.assets.open(DATABASE_NAME)         outputStream = FileOutputStream(db?.path)          val buffer = ByteArray(1024)         var length: Int = inputStream!!.read(buffer)         while (length > 0) {             outputStream.write(buffer, 0, length)             length = inputStream.read(buffer)         }         outputStream.flush()          val  copiedDb = mContext.openOrCreateDatabase(DATABASE_NAME, 0, null)          val isDbCreated = copiedDb != null          copiedDb.execSQL("PRAGMA user_version = $  DATABASE_VERSION")         copiedDb.close()          // DB_CREATED         val sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext)         val sharePrefEditor = sharedPref.edit()         sharePrefEditor.putBoolean(DB_CREATED, isDbCreated)         sharePrefEditor.apply()     } catch (e: IOException) {         e.printStackTrace()         throw Error("copyDatabaseFromAssets: Error copying database.")     } finally {         try {             outputStream?.close()             inputStream?.close()         }catch (e: IOException) {             e.printStackTrace()             throw Error("copyDatabaseFromAssets: Error closing stream.")         }     }  }  override fun onCreate(db: SQLiteDatabase?) {     mCreateDb = true }  override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {     if(newVersion > oldVersion) {         mUpgradeDb = true     } }  override fun onOpen(db: SQLiteDatabase?) {     if(mCreateDb) {         mCreateDb = false         copyDatabaseFromAssets(db)     }      if(mUpgradeDb) {         mUpgradeDb = false         copyDatabaseFromAssets(db)     } }  fun getWords(wordPrefix: String = ""): Cursor {     return if(wordPrefix.isBlank()) {         readableDatabase.query(DictionaryEntryContract.TABLE_NAME, null,                 null, null, null, null,                 "$  {DictionaryEntryContract.COLUMN_ID} ASC")     } else {         readableDatabase.query(DictionaryEntryContract.TABLE_NAME, null,                 "$  {DictionaryEntryContract.COLUMN_WORD} LIKE ?", arrayOf("$  wordPrefix%"),                 null, null, "$  {DictionaryEntryContract.COLUMN_ID} ASC")     } }  fun getWord(id: String): Cursor {     return readableDatabase.query(DictionaryEntryContract.TABLE_NAME, null,             "$  {DictionaryEntryContract.COLUMN_ID}= ?", arrayOf(id),             null, null, null) } } 

SearchListAdapter

package com.gumangan.uecfispiritualhymns  import android.content.Context import android.database.Cursor import android.graphics.Color import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.CursorAdapter import android.widget.TextView  class SearchListAdapter(context: Context, cursor: Cursor) : CursorAdapter(context, cursor, 0) { private class ViewHolder {     var txtWord: TextView? = null     var txtType: TextView? = null     var txtMeaning: TextView? = null      var wordColumnIndex: Int = 0     var typeColumnIndex: Int = 0     var meaningColumnIndex: Int = 0 }  override fun newView(context: Context?, cursor: Cursor?, parent: ViewGroup?): View {     val layoutInflater = LayoutInflater.from(context)     val newView = layoutInflater.inflate(R.layout.search_list_item, parent, false)      val viewHolder = ViewHolder()     viewHolder.txtWord = newView.findViewById<TextView>(R.id.txtWord)     viewHolder.txtType = newView.findViewById<TextView>(R.id.txtType)     viewHolder.txtMeaning = newView.findViewById<TextView>(R.id.txtMeaning)      viewHolder.wordColumnIndex = cursor!!.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_WORD)     viewHolder.typeColumnIndex = cursor!!.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_TYPE)     viewHolder.meaningColumnIndex = cursor!!.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_MEANING)      newView.tag = viewHolder      return newView }  override fun bindView(view: View?, context: Context?, cursor: Cursor?) {     val viewHolder = view!!.tag as ViewHolder      viewHolder.txtWord?.text = cursor?.getString(viewHolder.wordColumnIndex)     viewHolder.txtType?.text = cursor?.getString(viewHolder.typeColumnIndex)     viewHolder.txtMeaning?.text = cursor?.getString(viewHolder.meaningColumnIndex) }  override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {     val view = super.getView(position, convertView, parent)      if(position % 2 == 0) {         view.setBackgroundColor(Color.LTGRAY)     } else {         view.setBackgroundColor(Color.WHITE)     }      return view; } } 

DictionaryEntryContract

package com.gumangan.uecfispiritualhymns  import android.provider.BaseColumns  class DictionaryEntryContract : BaseColumns { private constructor()  companion object {     val TABLE_NAME = "english_words"      val COLUMN_ID = BaseColumns._ID     val COLUMN_WORD = "word"     val COLUMN_TYPE = "type"     val COLUMN_MEANING = "meaning" } } 

DictionaryActivity

package com.gumangan.uecfispiritualhymns  import android.app.SearchManager import android.content.Context import android.content.Intent import android.os.AsyncTask import android.os.Bundle import android.preference.PreferenceManager import android.support.v7.app.AppCompatActivity import android.support.v7.widget.Toolbar import android.support.v7.widget.SearchView import android.util.Log import android.view.Menu import android.view.MenuItem import android.widget.AdapterView import android.widget.ListView import com.google.android.gms.ads.AdRequest import com.google.android.gms.ads.AdView import com.google.android.gms.ads.MobileAds import java.lang.ref.WeakReference  class DictionaryActivity : AppCompatActivity() {  companion object {     val TAG = "DictionaryActivity"     val LAST_SEARCH_WORD: String = "LAST_SEARCH_WORD" }  var mDbHelper: DatabaseHelper? = null private var mSearchListAdapter: SearchListAdapter? = null private var mSearchQuery: String = ""  //Google Ads Banner Variable lateinit var mAdView : AdView  override fun onCreate(savedInstanceState: Bundle?) {     super.onCreate(savedInstanceState)     setContentView(R.layout.content_dictionary)      mSearchQuery = savedInstanceState?.getString(LAST_SEARCH_WORD) ?: ""     mDbHelper = DatabaseHelper(applicationContext)      if(!isDbLoaded()) {         showLoadingUI()         LoadViewTask(this).execute()     } else {         showDictUI()     }      /* TODO: Change ADMOB ID's when final building  */     //Google Ads     //MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713")     //Google Test Ads     MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713")      //Google Ads Banner     mAdView = findViewById(R.id.adView)     val adRequest = AdRequest.Builder().build()     mAdView.loadAd(adRequest)  }  private fun isDbLoaded(): Boolean {     val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)     return sharedPref.getBoolean(DatabaseHelper.DB_CREATED, false) }  private fun showLoadingUI() {     setContentView(R.layout.activity_dictionary_loading) }  private fun showDictUI() {     setContentView(R.layout.activity_dictionary)      val toolbar = findViewById<Toolbar>(R.id.toolbar)     setSupportActionBar(toolbar)      supportActionBar?.setIcon(R.mipmap.ic_launcher)      mSearchListAdapter = SearchListAdapter(applicationContext, mDbHelper!!.getWords(mSearchQuery))     val lstWords = (findViewById<ListView>(R.id.lstWords))     lstWords.adapter = mSearchListAdapter     lstWords.onItemClickListener = AdapterView.OnItemClickListener { _, _, _, id ->         val wordDetailIntent = Intent(applicationContext, WordDetailActivity::class.java)         wordDetailIntent.putExtra(WordDetailActivity.WORD_ID, "$  id")         startActivity(wordDetailIntent)     } }  override fun onSaveInstanceState(outState: Bundle?) {     super.onSaveInstanceState(outState)     outState?.putString(LAST_SEARCH_WORD, mSearchQuery) }  override fun onRestoreInstanceState(savedInstanceState: Bundle?) {     mSearchQuery = savedInstanceState?.getString(LAST_SEARCH_WORD) ?: ""     super.onRestoreInstanceState(savedInstanceState) }  override fun onNewIntent(intent: Intent?) {     super.onNewIntent(intent)      if(intent?.action.equals(Intent.ACTION_SEARCH)) {         val searchQuery = intent?.getStringExtra(SearchManager.QUERY) ?: ""         updateListByQuery(searchQuery)     } }  override fun onCreateOptionsMenu(menu: Menu): Boolean {     menuInflater.inflate(R.menu.menu_dictionary, menu)      val searchView: SearchView? = menu.findItem(R.id.action_search).actionView as? SearchView     val searchManager: SearchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager     searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))      searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener{         override fun onQueryTextSubmit(query: String?): Boolean {             return false         }          override fun onQueryTextChange(newText: String?): Boolean {             updateListByQuery(newText ?: "")             return true         }     })      return true }  private fun updateListByQuery(searchQuery: String) {     mSearchQuery = searchQuery     mSearchListAdapter?.changeCursor(mDbHelper!!.getWords(searchQuery)) }  override fun onOptionsItemSelected(item: MenuItem): Boolean {     return when (item.itemId) {         R.id.action_search -> {             onSearchRequested()             true         }         else -> super.onOptionsItemSelected(item)     } }  private class LoadViewTask(activity: DictionaryActivity) : AsyncTask<Void, Void, Void>() {     private var mActivity = WeakReference<DictionaryActivity>(activity)      override fun doInBackground(vararg params: Void): Void? {         if(getActivityInstance()?.mDbHelper?.readableDatabase?.isOpen == true) {             Log.d(TAG, "Db is OK.")         }         return null     }      override fun onPostExecute(result: Void?) {         if(getActivityInstance()?.isDbLoaded() == true) {             getActivityInstance()?.showDictUI()         }     }      private fun getActivityInstance() = mActivity.get() } } 

WordDetailActivity

package com.gumangan.uecfispiritualhymns  import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.widget.TextView  class WordDetailActivity : AppCompatActivity() {  companion object {     const val WORD_ID = "WORD_ID" }  override fun onCreate(savedInstanceState: Bundle?) {     super.onCreate(savedInstanceState)     setContentView(R.layout.activity_word_detail)      val wordId = intent.getStringExtra(WORD_ID) ?: ""     if(wordId.isBlank()) {         finish()     }      val dbHelper = DatabaseHelper(applicationContext)     val cursor = dbHelper.getWord(wordId)     if(cursor.moveToFirst()) {         val txtWord = findViewById<TextView>(R.id.txtWord)         val txtType = findViewById<TextView>(R.id.txtType)         val txtMeaning = findViewById<TextView>(R.id.txtMeaning)          txtWord?.text = cursor.getString(cursor.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_WORD))         txtType?.text = cursor.getString(cursor.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_TYPE))         txtMeaning?.text = cursor.getString(cursor.getColumnIndexOrThrow(DictionaryEntryContract.COLUMN_MEANING))     } } } 

activity_dictionary.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout  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="com.gumangan.uecfispiritualhymns.DictionaryActivity">  <android.support.design.widget.AppBarLayout     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:theme="@style/AppTheme.AppBarOverlay">      <android.support.v7.widget.Toolbar         android:id="@+id/toolbar"         android:layout_width="match_parent"         android:layout_height="?attr/actionBarSize"         android:background="?attr/colorPrimary"         app:popupTheme="@style/AppTheme.PopupOverlay" />  </android.support.design.widget.AppBarLayout>  <include layout="@layout/content_dictionary" />  </android.support.design.widget.CoordinatorLayout> 

content_dictionary.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout  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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.gumangan.uecfispiritualhymns.DictionaryActivity" tools:showIn="@layout/activity_dictionary">  <ListView     android:id="@+id/lstWords"     android:layout_width="0dp"     android:layout_height="0dp"     android:layout_marginBottom="0dp"     android:layout_marginEnd="0dp"     android:layout_marginStart="0dp"     android:layout_marginTop="0dp"     app:layout_constraintBottom_toBottomOf="parent"     app:layout_constraintEnd_toEndOf="parent"     app:layout_constraintStart_toStartOf="parent"     app:layout_constraintTop_toTopOf="parent" />       <!--Google Ads Banner Display-->     <com.google.android.gms.ads.AdView         xmlns:ads="http://schemas.android.com/apk/res-auto"         android:id="@+id/adView"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_alignParentBottom="true"         android:layout_centerHorizontal="true"         android:layout_marginBottom="5dp"         android:visibility="visible"         ads:adSize="LARGE_BANNER"         ads:adUnitId="ca-app-pub-3940256099942544/6300978111"         app:layout_constraintBottom_toBottomOf="parent"         app:layout_constraintLeft_toLeftOf="parent"         app:layout_constraintRight_toRightOf="parent">      </com.google.android.gms.ads.AdView>  </android.support.constraint.ConstraintLayout> 

activity_dictionary_loading.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout  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="com.gumangan.uecfispiritualhymns.DictionaryActivity">  <TextView     android:id="@+id/textView"     android:layout_width="0dp"     android:layout_height="wrap_content"     android:layout_marginBottom="8dp"     android:layout_marginEnd="8dp"     android:layout_marginStart="8dp"     android:layout_marginTop="8dp"     android:text="@string/dictionary_db_preparing"     android:textAlignment="center"     android:textSize="18sp"     app:layout_constraintBottom_toBottomOf="parent"     app:layout_constraintEnd_toEndOf="parent"     app:layout_constraintStart_toStartOf="parent"     app:layout_constraintTop_toTopOf="parent"     tools:text="@string/dictionary_db_preparing" /> </android.support.constraint.ConstraintLayout> 

search_list_item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp">  <TextView     android:id="@+id/txtWord"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="18sp"     android:textStyle="bold"     tools:text="Word" />  <TextView     android:id="@+id/txtType"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="14sp"     android:textStyle="italic"     tools:text="Type" />  <TextView     android:id="@+id/txtMeaning"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="18sp"     tools:text="Meaning" /> </LinearLayout> 

activity_word_detail.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" tools:context="com.gumangan.uecfispiritualhymns.WordDetailActivity">  <TextView     android:id="@+id/txtWord"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="20sp"     android:textStyle="bold"     tools:text="Word" />  <TextView     android:id="@+id/txtType"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="18sp"     android:textStyle="italic"     tools:text="Type" />  <TextView     android:id="@+id/txtMeaning"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:textSize="20sp"     tools:text="Meaning" />  </LinearLayout> 

This is the LogCat error

12-09 07:52:40.554 14146-14146/com.gumangan.uecfispiritualhymns E/AndroidRuntime: FATAL EXCEPTION: main     java.lang.RuntimeException: Unable to start activity ComponentInfo{com.gumangan.uecfispiritualhymns/com.gumangan.uecfispiritualhymns.DictionaryActivity}: java.lang.IllegalStateException: findViewById(R.id.adView) must not be null         at      android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)         at      android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)         at android.app.ActivityThread.access$  600(ActivityThread.java:130)         at android.app.ActivityThread$  H.handleMessage(ActivityThread.java:1195)         at android.os.Handler.dispatchMessage(Handler.java:99)         at android.os.Looper.loop(Looper.java:137)         at android.app.ActivityThread.main(ActivityThread.java:4745)         at java.lang.reflect.Method.invokeNative(Native Method)         at java.lang.reflect.Method.invoke(Method.java:511)         at com.android.internal.os.ZygoteInit$  MethodAndArgsCaller.run(ZygoteInit.java:786)         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)         at dalvik.system.NativeStart.main(Native Method)      Caused by: java.lang.IllegalStateException: findViewById(R.id.adView) must not be null         at com.gumangan.uecfispiritualhymns.DictionaryActivity.onCreate(DictionaryActivity.kt:57)         at android.app.Activity.performCreate(Activity.java:5008)         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)          at android.app.ActivityThread.access$  600(ActivityThread.java:130)          at android.app.ActivityThread$  H.handleMessage(ActivityThread.java:1195)          at android.os.Handler.dispatchMessage(Handler.java:99)          at android.os.Looper.loop(Looper.java:137)          at android.app.ActivityThread.main(ActivityThread.java:4745)          at java.lang.reflect.Method.invokeNative(Native Method)          at java.lang.reflect.Method.invoke(Method.java:511)          at com.android.internal.os.ZygoteInit$  MethodAndArgsCaller.run(ZygoteInit.java:786)          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)          at dalvik.system.NativeStart.main(Native Method)  

The app is about dictionary

Seeing Big Movement

I have just noticed that datacenters
-ab: 216.239.51.99
-ab: 216.239.51.103
-ab: 216.239.51.104
-kr: 66.102.11.104
-ab: 216.239.51.105
-ab: 216.239.51.147
and all the "New" datacenters

are showing drastically different results.

I don't know if this is an old cache or new changes.