Satisfy most warnings

Julien LepillerSun Jun 19 19:19:07+0200 2022

f74c442

Satisfy most warnings

.idea/misc.xml

11
<?xml version="1.0" encoding="UTF-8"?>
22
<project version="4">
3-
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
3+
  <component name="DesignSurface">
4+
    <option name="filePathToZoomLevelMap">
5+
      <map>
6+
        <entry key="../../../../../../layout/custom_preview.xml" value="0.23385416666666667" />
7+
      </map>
8+
    </option>
9+
  </component>
10+
  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
411
    <output url="file://$PROJECT_DIR$/build/classes" />
512
  </component>
613
  <component name="ProjectType">

app/src/main/java/eu/lepiller/nani/AboutActivity.java

1818
        Button report_button = findViewById(R.id.report_button);
1919
        Button mozc_button = findViewById(R.id.mozc_button);
2020
21-
        sources_button.setOnClickListener(new View.OnClickListener() {
22-
            @Override
23-
            public void onClick(View v) {
24-
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/nani-project/nani-app"));
25-
                startActivity(browserIntent);
26-
            }
21+
        sources_button.setOnClickListener(v -> {
22+
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/nani-project/nani-app"));
23+
            startActivity(browserIntent);
2724
        });
2825
29-
        report_button.setOnClickListener(new View.OnClickListener() {
30-
            @Override
31-
            public void onClick(View v) {
32-
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/nani-project/nani-app/issues"));
33-
                startActivity(browserIntent);
34-
            }
26+
        report_button.setOnClickListener(v -> {
27+
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://framagit.org/nani-project/nani-app/issues"));
28+
            startActivity(browserIntent);
3529
        });
3630
37-
        mozc_button.setOnClickListener(new View.OnClickListener() {
38-
            @Override
39-
            public void onClick(View v) {
40-
                String appPackageName = "org.mozc.android.inputmethod.japanese";
41-
                try {
42-
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
43-
                } catch (android.content.ActivityNotFoundException e) {
44-
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
45-
                }
31+
        mozc_button.setOnClickListener(v -> {
32+
            String appPackageName = "org.mozc.android.inputmethod.japanese";
33+
            try {
34+
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
35+
            } catch (android.content.ActivityNotFoundException e) {
36+
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
4637
            }
4738
        });
4839
    }

app/src/main/java/eu/lepiller/nani/DictionaryActivity.java

11
package eu.lepiller.nani;
22
3+
import android.app.Activity;
34
import android.content.Intent;
45
import android.os.AsyncTask;
56
import android.os.Bundle;
7+
8+
import androidx.activity.result.contract.ActivityResultContracts;
69
import androidx.appcompat.app.AppCompatActivity;
710
import androidx.lifecycle.LiveData;
811
import androidx.lifecycle.MutableLiveData;
9-
import androidx.lifecycle.Observer;
1012
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
1113
1214
import android.util.Log;

6163
        adapter = new DictionariesAdapter(this, dictionaries);
6264
        list_view.setAdapter(adapter);
6365
64-
        langAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, langs);
66+
        langAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, langs);
6567
        langAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
6668
        lang_view.setAdapter(langAdapter);
6769

7173
            refresh();
7274
        }
7375
74-
        list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
75-
            @Override
76-
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
77-
                Intent intent = new Intent(DictionaryActivity.this, DictionaryDownloadActivity.class);
78-
                intent.putExtra(DictionaryDownloadActivity.EXTRA_DICTIONARY, DictionaryFactory.get(position).getName());
79-
                startActivityForResult(intent, DICO_REQUEST);
80-
            }
76+
        list_view.setOnItemClickListener((parent, view, position, id) -> {
77+
            Intent intent = new Intent(DictionaryActivity.this, DictionaryDownloadActivity.class);
78+
            intent.putExtra(DictionaryDownloadActivity.EXTRA_DICTIONARY, DictionaryFactory.get(position).getName());
79+
80+
            registerForActivityResult(
81+
                    new ActivityResultContracts.StartActivityForResult(),
82+
                    result -> {
83+
                        if (result.getResultCode() == Activity.RESULT_OK) {
84+
                            updateDataSet();
85+
                        }
86+
                    }).launch(intent);
8187
        });
8288
8389
        lang_view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

102108
    protected void onResume() {
103109
        super.onResume();
104110
        setObserver();
105-
        refresher.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
106-
            @Override
107-
            public void onRefresh() {
108-
                refresh();
109-
            }
110-
        });
111+
        refresher.setOnRefreshListener(this::refresh);
111112
        updateDataSet();
112113
    }
113114

123124
124125
    private void setObserver() {
125126
        LiveData<Boolean> data = DownloadTask.getRefreshingData();
126-
        data.observe(this, new Observer<Boolean>() {
127-
            @Override
128-
            public void onChanged(Boolean refreshing) {
129-
                refresher.setRefreshing(refreshing);
130-
                if(!refreshing)
131-
                    updateDataSet();
132-
            }
127+
        data.observe(this, refreshing -> {
128+
            refresher.setRefreshing(refreshing);
129+
            if(!refreshing)
130+
                updateDataSet();
133131
        });
134132
    }
135133

199197
        adapter.notifyDataSetChanged();
200198
        langAdapter.notifyDataSetChanged();
201199
    }
202-
203-
    @Override
204-
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
205-
        super.onActivityResult(requestCode, resultCode, data);
206-
        if (requestCode == DICO_REQUEST) {
207-
            updateDataSet();
208-
        }
209-
    }
210-
211200
}

app/src/main/java/eu/lepiller/nani/DictionaryDownloadActivity.java

55
import android.os.Build;
66
77
import androidx.appcompat.app.AppCompatActivity;
8+
import androidx.core.content.res.ResourcesCompat;
89
import androidx.lifecycle.LiveData;
910
import androidx.lifecycle.Observer;
1011

8081
        if (dictionaryName == null)
8182
            return;
8283
83-
        observer = new Observer<DictionaryDownloadService.DownloadData>() {
84-
            @Override
85-
            public void onChanged(DictionaryDownloadService.DownloadData downloadData) {
86-
                boolean pending = false;
87-
                for(String n: downloadData.downloading) {
88-
                    if(n.equals(dictionaryName)) {
89-
                        pending = true;
90-
                        break;
91-
                    }
84+
        observer = downloadData -> {
85+
            boolean pending = false;
86+
            for(String n: downloadData.downloading) {
87+
                if(n.equals(dictionaryName)) {
88+
                    pending = true;
89+
                    break;
9290
                }
93-
                Log.d(TAG, "onChanged: " + downloadData.currentName);
94-
95-
                if(dictionaryName.equals(downloadData.currentName)) {
96-
                    download_bar.setMax(100);
97-
                    if(downloadData.currentProgress >= 0) {
98-
                        download_bar.setIndeterminate(false);
99-
                        download_bar.setProgress(downloadData.currentProgress);
100-
                    } else {
101-
                        download_bar.setIndeterminate(true);
102-
                    }
103-
                    updateLayout(true);
104-
                } else if(pending) {
91+
            }
92+
            Log.d(TAG, "onChanged: " + downloadData.currentName);
93+
94+
            if(dictionaryName.equals(downloadData.currentName)) {
95+
                download_bar.setMax(100);
96+
                if(downloadData.currentProgress >= 0) {
97+
                    download_bar.setIndeterminate(false);
98+
                    download_bar.setProgress(downloadData.currentProgress);
99+
                } else {
105100
                    download_bar.setIndeterminate(true);
106-
                    updateLayout(true);
101+
                }
102+
                updateLayout(true);
103+
            } else if(pending) {
104+
                download_bar.setIndeterminate(true);
105+
                updateLayout(true);
106+
            } else {
107+
                if(d.isDownloaded()) {
108+
                    download_bar.setProgress(100);
107109
                } else {
108-
                    if(d.isDownloaded()) {
109-
                        download_bar.setProgress(100);
110-
                    } else {
111-
                        download_bar.setProgress(d.getSize()*100 / d.getExpectedFileSize());
112-
                    }
113-
                    updateLayout(false);
110+
                    download_bar.setProgress(d.getSize()*100 / d.getExpectedFileSize());
114111
                }
112+
                updateLayout(false);
115113
            }
116114
        };
117115
        data.observe(this, observer);

175173
        else
176174
            size_view.setText(String.format(getResources().getString(R.string.dictionary_size_mb), size/1000000));
177175
178-
        trash_button.setOnClickListener(new View.OnClickListener() {
179-
            @Override
180-
            public void onClick(View v) {
181-
                d.remove();
182-
                updateLayout(isDownloading);
183-
            }
176+
        trash_button.setOnClickListener(v -> {
177+
            d.remove();
178+
            updateLayout(isDownloading);
184179
        });
185180
    }
186181
187182
    private void setIcon(ImageView download_button, int drawableResId) {
188-
        Drawable drawable;
189-
        if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
190-
            drawable = getResources().getDrawable(drawableResId, getTheme());
191-
        } else {
192-
            drawable = getResources().getDrawable(drawableResId);
193-
        }
183+
        Drawable drawable = ResourcesCompat.getDrawable(getResources(), drawableResId, getTheme());
194184
        download_button.setImageDrawable(drawable);
195185
    }
196186
}

app/src/main/java/eu/lepiller/nani/DictionaryDownloadService.java

6666
                .setContentText(getString(R.string.downloading))
6767
                .setOnlyAlertOnce(true);
6868
        downloadQueue = new DownloadQueue();
69-
        Downloader downloadThread = new Downloader(new Runnable() {
70-
            @Override
71-
            public void run() {
72-
                stopForeground(true);
73-
                stopSelf();
74-
            }
69+
        Downloader downloadThread = new Downloader(() -> {
70+
            stopForeground(true);
71+
            stopSelf();
7572
        });
7673
        new Thread(downloadThread).start();
7774
    }

122119
        final DownloadData downloadData = new DownloadData(name, progress, downloadQueue.downloadQueue());
123120
124121
        Handler threadHandler = new Handler(Looper.getMainLooper());
125-
        threadHandler.post(new Runnable() {
126-
            @Override
127-
            public void run() {
128-
                if(data == null)
129-
                    data = new MutableLiveData<>();
130-
                data.setValue(downloadData);
131-
            }
122+
        threadHandler.post(() -> {
123+
            if(data == null)
124+
                data = new MutableLiveData<>();
125+
            data.setValue(downloadData);
132126
        });
133127
    }
134128
135129
    private static class DownloadQueue {
136-
        private ArrayList<String> downloadQueue = new ArrayList<>();
130+
        private final ArrayList<String> downloadQueue = new ArrayList<>();
137131
        private boolean waitsForFirstWork = true;
138132
        private boolean stopAsked = false;
139-
        private ReentrantLock mutex = new ReentrantLock();
133+
        private final ReentrantLock mutex = new ReentrantLock();
140134
141135
        ArrayList<String> downloadQueue() {
142136
            try {

221215
    }
222216
223217
    private class Downloader implements Runnable {
224-
        private Runnable onStop;
218+
        private final Runnable onStop;
225219
226220
        Downloader(Runnable onStop) {
227221
            this.onStop = onStop;

app/src/main/java/eu/lepiller/nani/HelpActivity.java

2424
    }
2525
2626
    private<T> View.OnClickListener getOpenListener(final Class<T> c) {
27-
        return new View.OnClickListener() {
28-
            @Override
29-
            public void onClick(View v) {
30-
                Intent intent = new Intent(HelpActivity.this, c);
31-
                startActivity(intent);
32-
            }
27+
        return v -> {
28+
            Intent intent = new Intent(HelpActivity.this, c);
29+
            startActivity(intent);
3330
        };
3431
    }
3532
}

app/src/main/java/eu/lepiller/nani/HelpPitchActivity.java

1616
        setContentView(R.layout.activity_help_pitch);
1717
1818
        Button wikiButton = findViewById(R.id.wiki_button);
19-
        wikiButton.setOnClickListener(new View.OnClickListener() {
20-
            @Override
21-
            public void onClick(View v) {
22-
                Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help_pitch_wiki_link)));
23-
                startActivity(browserIntent);
24-
            }
19+
        wikiButton.setOnClickListener(v -> {
20+
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help_pitch_wiki_link)));
21+
            startActivity(browserIntent);
2522
        });
2623
    }
2724
}
2724=
2825=
\ No newline at end of file

app/src/main/java/eu/lepiller/nani/MainActivity.java

11
package eu.lepiller.nani;
22
3+
import android.annotation.SuppressLint;
34
import android.content.Intent;
45
import android.content.SharedPreferences;
56
import android.os.AsyncTask;

5152
5253
    static final String TAG = "MAIN";
5354
55+
    // At this point we really need to redraw pagerAdapter, so suppress the warning.
56+
    @SuppressLint("NotifyDataSetChanged")
5457
    @Override
5558
    protected void onCreate(Bundle savedInstanceState) {
5659
        super.onCreate(savedInstanceState);

8386
        tabLayout.addTab(tabLayout.newTab().setText(R.string.tab_kanji));
8487
8588
        new TabLayoutMediator(tabLayout, viewPager2,
86-
                new TabLayoutMediator.TabConfigurationStrategy() {
87-
                    @Override
88-
                    public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
89-
                        tab.setText(position == 0? R.string.tab_results: R.string.tab_kanji);
90-
                    }
91-
                }
89+
                (tab, position) -> tab.setText(position == 0? R.string.tab_results: R.string.tab_kanji)
9290
        ).attach();
9391
9492
        try {

9896
            e.printStackTrace();
9997
        }
10098
101-
        radical_button.setOnClickListener(new View.OnClickListener() {
102-
            @Override
103-
            public void onClick(View v) {
104-
                try {
105-
                    DictionaryFactory.getRadicalDictionary(getApplicationContext());
106-
                    radical_selector.setVisibility(View.VISIBLE);
107-
                    result_layout.setVisibility(View.INVISIBLE);
108-
                    search_form.setIconified(false);
109-
                } catch (NoDictionaryException e) {
110-
                    Snackbar.make(search_form, getString(R.string.no_radical_dict), Snackbar.LENGTH_LONG).show();
111-
                }
99+
        radical_button.setOnClickListener(v -> {
100+
            try {
101+
                DictionaryFactory.getRadicalDictionary(getApplicationContext());
102+
                radical_selector.setVisibility(View.VISIBLE);
103+
                result_layout.setVisibility(View.INVISIBLE);
104+
                search_form.setIconified(false);
105+
            } catch (NoDictionaryException e) {
106+
                Snackbar.make(search_form, getString(R.string.no_radical_dict), Snackbar.LENGTH_LONG).show();
112107
            }
113108
        });
114109
115-
        radical_selector.setOnCloseEventListener(new View.OnClickListener() {
116-
            @Override
117-
            public void onClick(View v) {
118-
                closeRadicals();
119-
            }
120-
        });
110+
        radical_selector.setOnCloseEventListener(v -> closeRadicals());
121111
122-
        radical_selector.setOnClickEventListener(new View.OnClickListener() {
123-
            @Override
124-
            public void onClick(View v) {
125-
                String k = ((Button)v).getText().toString();
126-
                search_form.setQuery(search_form.getQuery() + k, false);
127-
            }
112+
        radical_selector.setOnClickEventListener(v -> {
113+
            String k = ((Button)v).getText().toString();
114+
            search_form.setQuery(search_form.getQuery() + k, false);
128115
        });
129116
130-
        radical_selector.setOnHelpEventListener(new View.OnClickListener() {
131-
            @Override
132-
            public void onClick(View v) {
133-
                Intent intent = new Intent(MainActivity.this, HelpRadicalActivity.class);
134-
                startActivity(intent);
135-
            }
117+
        radical_selector.setOnHelpEventListener(v -> {
118+
            Intent intent = new Intent(MainActivity.this, HelpRadicalActivity.class);
119+
            startActivity(intent);
136120
        });
137121
138122
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {

155139
        } else if(key.compareTo(SettingsActivity.KEY_PREF_READING_STYLE) == 0) {
156140
            readingStyle = getReadingSizePref(sharedPreferences);
157141
            pagerAdapter.setReadingStyle(readingStyle);
158-
            pagerAdapter.notifyDataSetChanged();
142+
            pagerAdapter.notifyItemChanged(0);
159143
        }
160144
    }
161145
162146
    private int getRadSizePref(SharedPreferences sharedPrefs) {
163147
        String prefRadSize = sharedPrefs.getString(SettingsActivity.KEY_PREF_RAD_SIZE, "122");
164-
        if(prefRadSize == null)
165-
            prefRadSize = "122";
166148
        return Integer.parseInt(prefRadSize);
167149
    }
168150
169151
    private String getReadingSizePref(SharedPreferences sharedPreferences) {
170-
        String prefReadingStyle = sharedPreferences.getString(SettingsActivity.KEY_PREF_READING_STYLE, "furigana");
171-
        if(prefReadingStyle == null)
172-
            prefReadingStyle = "furigana";
173-
        return prefReadingStyle;
152+
        return sharedPreferences.getString(SettingsActivity.KEY_PREF_READING_STYLE, "furigana");
174153
    }
175154
176155
    private static class SearchTask extends AsyncTask<String, Integer, SearchResult> {

279258
                    }
280259
                    sb.append(s);
281260
                }
282-
                feedback_text.setText(String.format(getString(R.string.feedback_no_result_tried), sb.toString()));
261+
                feedback_text.setText(String.format(getString(R.string.feedback_no_result_tried), sb));
283262
            }
284263
            return;
285264
        }

297276
            final String moji = converter.convertRomajiToHiragana(r.getText());
298277
            feedback_text.setText(String.format(getString(R.string.feedback_didyoumean), moji));
299278
300-
            feedback_text.setOnClickListener(new View.OnClickListener() {
301-
                @Override
302-
                public void onClick(View v) {
303-
                    search_form.setQuery(moji, true);
304-
                    feedback_text.setOnClickListener(null);
305-
                }
279+
            feedback_text.setOnClickListener(v -> {
280+
                search_form.setQuery(moji, true);
281+
                feedback_text.setOnClickListener(null);
306282
            });
307283
        }
308284

314290
315291
        pagerAdapter.setKanjiResults(kanjiResults);
316292
        pagerAdapter.setResults(searchResult);
317-
        pagerAdapter.notifyDataSetChanged();
293+
        pagerAdapter.notifyItemChanged(0);
294+
        pagerAdapter.notifyItemChanged(1);
318295
    }
319296
320297
    @Override

327304
328305
        search_form.setQueryHint(getResources().getString(R.string.search_hint));
329306
330-
        search_form.setOnCloseListener(new SearchView.OnCloseListener() {
331-
            @Override
332-
            public boolean onClose() {
333-
                closeRadicals();
334-
                return false;
335-
            }
307+
        search_form.setOnCloseListener(() -> {
308+
            closeRadicals();
309+
            return false;
336310
        });
337311
338312
        search_form.setOnQueryTextListener(new SearchView.OnQueryTextListener() {

347321
                    return false;
348322
                }
349323
350-
                pagerAdapter.setKanjiResults(new ArrayList<KanjiResult>());
351-
                pagerAdapter.setResults(new ArrayList<Result>());
352-
                pagerAdapter.notifyDataSetChanged();
353-
324+
                pagerAdapter.setKanjiResults(new ArrayList<>());
325+
                pagerAdapter.setResults(new ArrayList<>());
326+
                pagerAdapter.notifyItemChanged(0);
327+
                pagerAdapter.notifyItemChanged(1);
354328
                search_form.setEnabled(false);
355329
                feedback_text.setText(R.string.feedback_progress);
356330

app/src/main/java/eu/lepiller/nani/PitchDiagramView.java

1616
import java.util.ArrayList;
1717
1818
public class PitchDiagramView extends View {
19-
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
19+
    private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
2020
    private int textColor = Color.BLACK;
2121
    private int pitchColor = Color.BLACK;
2222
    private ArrayList<Pair<String, Boolean>> pitchedMora = new ArrayList<>();

2525
2626
    private float textSize = 32;
2727
28-
    private static final String TAG = "PITCHVIEW";
29-
3028
    public PitchDiagramView(Context context) {
3129
        super(context);
3230
        setDefaults();

app/src/main/java/eu/lepiller/nani/RadicalSelectorView.java

110110
                radicalButton.setTextSize(getRadFontSize());
111111
                radicalButton.setLayoutParams(new FlexboxLayout.LayoutParams(radSize, radSize));
112112
113-
                radicalButton.setOnClickListener(new OnClickListener() {
114-
                    @Override
115-
                    public void onClick(View v) {
116-
                        boolean checked = ((ToggleButton) v).isChecked();
117-
                        if (checked) {
118-
                            selected.add(radical);
119-
                        } else {
120-
                            selected.remove(radical);
121-
                        }
122-
123-
                        String[] set = new String[selected.size()];
124-
                        for(int i=0; i<selected.size(); i++) {
125-
                            set[i] = selected.get(i);
126-
                        }
127-
                        new DictionarySearchTask(RadicalSelectorView.this, dictionary).execute(set);
113+
                radicalButton.setOnClickListener(v -> {
114+
                    boolean checked = ((ToggleButton) v).isChecked();
115+
                    if (checked) {
116+
                        selected.add(radical);
117+
                    } else {
118+
                        selected.remove(radical);
128119
                    }
120+
121+
                    String[] set = new String[selected.size()];
122+
                    for(int i=0; i<selected.size(); i++) {
123+
                        set[i] = selected.get(i);
124+
                    }
125+
                    new DictionarySearchTask(RadicalSelectorView.this, dictionary).execute(set);
129126
                });
130127
                box.addView(radicalButton);
131128
            }

app/src/main/java/eu/lepiller/nani/ResultPagerAdapter.java

11
package eu.lepiller.nani;
22
3+
import android.annotation.SuppressLint;
34
import android.content.Context;
45
import android.content.Intent;
56
import android.text.Html;

2627
    static List<Result> results = new ArrayList<>();
2728
    static List<KanjiResult> kanjiResults = new ArrayList<>();
2829
    private static String readingStyle = "furigana";
29-
    private Context context;
30+
    private final Context context;
3031
3132
    static final String TAG = "RESULTS_PAGER";
3233
3334
    public static class ViewHolder extends RecyclerView.ViewHolder {
34-
        private LinearLayout result_view;
35-
        private Context context;
35+
        private final LinearLayout result_view;
36+
        private final Context context;
3637
3738
        ViewHolder(View view, Context context) {
3839
            super(view);

9899
99100
                    StringBuilder sb = new StringBuilder();
100101
                    boolean separator1 = false;
101-
                    for (String s : meanings.get(lang)) {
102-
                        if (separator1)
103-
                            sb.append(context.getResources().getString(R.string.sense_separator));
104-
                        else
105-
                            separator1 = true;
106-
                        sb.append(s);
102+
                    List<String> langs = meanings.get(lang);
103+
                    if(langs != null) {
104+
                        for (String s : langs) {
105+
                            if (separator1)
106+
                                sb.append(context.getResources().getString(R.string.sense_separator));
107+
                            else
108+
                                separator1 = true;
109+
                            sb.append(s);
110+
                        }
107111
                    }
108112
                    sense_view.setText(Html.fromHtml(sb.toString()));
109113

149153
                if(pitch != null) {
150154
                    pitch_view.setVisibility(View.VISIBLE);
151155
                    pitch_view.setText(pitch);
152-
                    pitch_view.setOnClickListener(new View.OnClickListener() {
153-
                        @Override
154-
                        public void onClick(View v) {
155-
                            Intent intent = new Intent(context, HelpPitchActivity.class);
156-
                            context.startActivity(intent);
157-
                        }
156+
                    pitch_view.setOnClickListener(v -> {
157+
                        Intent intent = new Intent(context, HelpPitchActivity.class);
158+
                        context.startActivity(intent);
158159
                    });
159160
                }
160161

193194
        }
194195
    }
195196
196-
    private LayoutInflater mInflater;
197+
    private final LayoutInflater mInflater;
197198
    ResultPagerAdapter(Context context) {
198199
        this.mInflater = LayoutInflater.from(context);
199200
        this.context = context;

219220
        return 2;
220221
    }
221222
223+
    // Changing the style requires redrawing everything, so suppress warning
224+
    @SuppressLint("NotifyDataSetChanged")
222225
    public void setReadingStyle(String readingStyle) {
223226
        ResultPagerAdapter.readingStyle = readingStyle;
224227
        Log.d(TAG, "reading style updated to " + readingStyle);
225228
        notifyDataSetChanged();
226229
    }
227230
231+
    @SuppressLint("NotifyDataSetChanged")
228232
    public void setKanjiResults(List<KanjiResult> kanjiResults) {
229233
        if(kanjiResults == null)
230234
            return;

235239
        notifyDataSetChanged();
236240
    }
237241
242+
    @SuppressLint("NotifyDataSetChanged")
238243
    public void setResults(List<Result> results) {
239244
        if(results == null)
240245
            return;

app/src/main/java/eu/lepiller/nani/dictionary/DictionariesAdapter.java

1818
import eu.lepiller.nani.R;
1919
2020
public class DictionariesAdapter extends ArrayAdapter<Dictionary> {
21-
    private Context context;
21+
    private final Context context;
2222
2323
    public DictionariesAdapter(Context context, ArrayList<Dictionary> dictionaries) {
2424
        super(context, 0, dictionaries);

app/src/main/java/eu/lepiller/nani/dictionary/Dictionary.java

55
import android.graphics.Canvas;
66
import android.graphics.drawable.BitmapDrawable;
77
import android.graphics.drawable.Drawable;
8-
import android.os.Build;
98
import android.util.Pair;
109
10+
import androidx.core.content.res.ResourcesCompat;
11+
1112
import java.io.File;
1213
import java.io.FileInputStream;
1314
import java.io.FileNotFoundException;

2122
import eu.lepiller.nani.R;
2223
2324
abstract public class Dictionary {
24-
    private String name;
25-
    private String description, fullDescription, lang;
26-
    private int expectedFileSize;
27-
    private int expectedEntries;
28-
    private String sha256;
29-
    private File file, temporaryFile;
25+
    private final String name;
26+
    private final String description, fullDescription, lang;
27+
    private final int expectedFileSize;
28+
    private final int expectedEntries;
29+
    private final String sha256;
30+
    private final File file, temporaryFile;
3031
31-
    private Drawable drawable=null, newDrawable=null;
32+
    private Drawable drawable, newDrawable;
3233
3334
    Dictionary(String name, String description, String fullDescription, File cacheDir, int fileSize, int entries, String hash, String lang) {
3435
        this.name = name;

8485
    public Drawable getDrawable(Context context) {
8586
        if(drawable == null) {
8687
            int drawableResId = getDrawableId();
87-
            if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
88-
                drawable = context.getResources().getDrawable(drawableResId, context.getTheme());
89-
            } else {
90-
                drawable = context.getResources().getDrawable(drawableResId);
91-
            }
88+
            drawable = ResourcesCompat.getDrawable(context.getResources(), drawableResId, context.getTheme());
9289
        }
9390
        return drawable;
9491
    }

115112
            // Ensure we have the base icon
116113
            getDrawable(context);
117114
118-
            Drawable star;
119-
            if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
120-
                star = context.getResources().getDrawable(R.drawable.ic_star, context.getTheme());
121-
            } else {
122-
                star = context.getResources().getDrawable(R.drawable.ic_star);
123-
            }
115+
            Drawable star = ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_star, context.getTheme());
124116
125117
            canvas.drawBitmap(drawableToBitmap(drawable, 640, 640), 0, 0, null);
126118
            canvas.drawBitmap(drawableToBitmap(star, 220, 220), 390, 390, null);

app/src/main/java/eu/lepiller/nani/dictionary/FileDictionary.java

3636
        void skipVals(RandomAccessFile file, long pos) throws IOException;
3737
    }
3838
39-
    private String mUrl;
39+
    private final String mUrl;
4040
    private final static String TAG = "FileDictionary";
4141
4242
    FileDictionary(String name, String description, String fullDescription, File cacheDir, String url,

app/src/main/java/eu/lepiller/nani/dictionary/IncompatibleFormatException.java

11
package eu.lepiller.nani.dictionary;
22
33
public class IncompatibleFormatException extends DictionaryException {
4-
    private String name;
4+
    private final String name;
55
66
    IncompatibleFormatException(String name) {
77
        this.name = name;

app/src/main/java/eu/lepiller/nani/dictionary/NoResultDictionaryException.java

44
import java.util.List;
55
66
public class NoResultDictionaryException extends DictionaryException {
7-
    private ArrayList<String> tried;
7+
    private final ArrayList<String> tried;
88
99
    public NoResultDictionaryException(ArrayList<String> tried) {
1010
        this.tried = tried;

app/src/main/java/eu/lepiller/nani/dictionary/ResultDictionary.java

164164
                readingHuffman = loadHuffman(file);
165165
                meaningHuffman = loadHuffman(file);
166166
167-
                logHuffman(readingHuffman, new ArrayList<Boolean>());
167+
                logHuffman(readingHuffman, new ArrayList<>());
168168
169169
                // Search in Japanese, by kanji and reading
170170
                Log.d(TAG, "search: by kanji and reading");

app/src/main/java/eu/lepiller/nani/dictionary/WadokuPitchDictionary.java

6363
                file.readInt();
6464
6565
                huffman = loadHuffman(file);
66-
                logHuffman(huffman, new ArrayList<Boolean>());
66+
                logHuffman(huffman, new ArrayList<>());
6767
6868
                triePos = file.getFilePointer();
6969
            }

app/src/main/java/eu/lepiller/nani/result/KanjiResult.java

55
66
public class KanjiResult {
77
    public static class Sense {
8-
        private String lang, content;
8+
        private final String lang, content;
99
        public Sense(String lang, String content) {
1010
            this.lang = lang;
1111
            this.content = content;

1919
            return lang;
2020
        }
2121
    }
22-
    private String kanji;
23-
    private int stroke;
24-
    private List<Sense> senses;
22+
    private final String kanji;
23+
    private final int stroke;
24+
    private final List<Sense> senses;
2525
    private List<String> on;
26-
    private List<String> kun;
27-
    private List<String> nanori;
26+
    private final List<String> kun;
27+
    private final List<String> nanori;
2828
2929
    public KanjiResult(String kanji, int stroke, List<Sense> senses, List<String> kun, List<String> on, List<String> nanori) {
3030
        this.kanji = kanji;

app/src/main/java/eu/lepiller/nani/result/Result.java

1414
1515
public class Result {
1616
    public static class Source {
17-
        private ArrayList<String> content;
18-
        private boolean wasei;
19-
        private String language;
17+
        private final ArrayList<String> content;
18+
        private final boolean wasei;
19+
        private final String language;
2020
2121
        public Source(ArrayList<String> content, boolean wasei, String language) {
2222
            this.content = content;

2626
    }
2727
2828
    public static class Sense {
29-
        private ArrayList<String> references, limits, infos, glosses;
30-
        private String language;
31-
        private ArrayList<Source> sources;
29+
        private final ArrayList<String> references, limits, infos, glosses;
30+
        private final String language;
31+
        private final ArrayList<Source> sources;
3232
3333
        public Sense(ArrayList<String> references, ArrayList<String> limits, ArrayList<String> infos,
3434
                     ArrayList<Source> sources, ArrayList<String> glosses,

5555
    }
5656
5757
    public static class Reading {
58-
        private ArrayList<String> kanjis, infos, readings, pitches;
58+
        private final ArrayList<String> kanjis, infos, readings, pitches;
5959
6060
        public Reading(ArrayList<String> kanjis, ArrayList<String> infos, ArrayList<String> readings) {
6161
            this.kanjis = kanjis;

7777
        }
7878
    }
7979
80-
    private ArrayList<String> kanjis;
81-
    private ArrayList<Reading> readings;
82-
    private ArrayList<Sense> senses;
83-
    private int score;
80+
    private final ArrayList<String> kanjis;
81+
    private final ArrayList<Reading> readings;
82+
    private final ArrayList<Sense> senses;
83+
    private final int score;
8484
8585
    public Result(ArrayList<String> kanjis, ArrayList<Reading> readings, ArrayList<Sense> senses, int score) {
8686
        this.kanjis = kanjis;

176176
                    if(Character.UnicodeBlock.of(c) == KATAKANA) {
177177
                        current.append("[");
178178
                        current.append(c);
179-
                        current.append(converter.convertRomajiToHiragana(converter.convertKanaToRomaji(new String(new char[]{c}))));
179+
                        current.append(converter.convertRomajiToHiragana(converter.convertKanaToRomaji(String.valueOf(c))));
180180
                        current.append("]");
181181
                    } else {
182182
                        current.append(c);

186186
        }
187187
        current.append("$");
188188
189-
        Log.v("RESULT", "regex: " + current.toString());
189+
        Log.v("RESULT", "regex: " + current);
190190
191191
        Pattern p = Pattern.compile(current.toString());
192192
        Matcher m = p.matcher(reading);

214214
                current.append(" ");
215215
            }
216216
        }
217-
        Log.v("RESULT", "Finaly: " + current.toString());
217+
        Log.v("RESULT", "Finaly: " + current);
218218
        return current.toString();
219219
    }
220220