I'm new to threading but I have an EditText view which whenever is getting out of focused it fills a RecyclerView with image logos using the user's input from EditText. But, whenever the user gets out of focuse and the method is called everything stops for a while(which mean im bad at threading). How can I improve this code so it can run smoothly?
My activity class:
public class addItem extends AppCompatActivity {
LoadingDialog loadingDialog;
RecyclerView imgList;
ArrayList<Bitmap> bitmapList = new ArrayList<>();
BitmapAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
/*
/ Code Unnecessary to the problem…
*/
et_title.setOnFocusChangeListener((v, hasFocus) -> {
if(!hasFocus){
getImageLogo(et_title.getText().toString());
}
});
}
@SuppressLint("NotifyDataSetChanged")
private void getImageLogo(String serviceName){
googleRequest googleList = new googleRequest(serviceName);
googleList.start();
try {
googleList.join();
} catch (InterruptedException e) {
Log.e("Interrupted Error","Thread Was Interrupted unexpectedly",e);
}
if(googleList.getImgRealList() != null) {
bitmapList.clear();
bitmapList.addAll(googleList.getImgRealList());
}else {
bitmapList.clear();
}
adapter.notifyDataSetChanged();
}
My googleRequest class:
public class googleRequest extends Thread {
private ArrayList<Bitmap> imgRealList;
private final String keyword;
public googleRequest(String keyword){
this.keyword = keyword;
}
public ArrayList<Bitmap> getImgRealList() {
return imgRealList;
}
@Override
public void run() {
String newKeyword = keyword.toLowerCase(Locale.ROOT);
newKeyword = newKeyword.replace(' ',' ');
String url = "https://www.google.gr/search?bih=427&biw=1835&hl=el&gbv=1&tbm=isch&og=&ags=&q=" newKeyword;
try {
Document document = Jsoup.connect(url).get();
imgRealList = new ArrayList<>();
Elements imgList = document.select("img");
for (int i=1;i<imgList.size();i ) {
if(i==8)
break;
String imgSrc = imgList.get(i).absUrl("src");
InputStream input = new java.net.URL(imgSrc).openStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
imgRealList.add(bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
CodePudding user response:
Here is an example of how it can be implemented using a callback as I have mentioned in comments. For this, we need to define a callback inerface I named it as following, you can change the names for your convenience.
RequestConsumer it is simple java interface.
/// Must be executed in the UI (main) thread.
@MainThread
public interface RequestConsumer {
void onRequestResult(List<Bitmap> bitmaps);
}
googleRequest thread class.
public class googleRequest extends Thread {
private ArrayList<Bitmap> imgRealList;
private final String keyword;
/*
We will use the request consumer callback in order to deliver the results
to the UI from background. Since we need to touch the UI by this callback
we ensure that it will execute within the UI thread's queue using the
uiHandler.
*/
private final RequestConsumer requestConsumer;
private final Handler uiHandler = new Handler(Looper.getMainLooper());
public googleRequest(@NonNull String keyword, @NonNull RequestConsumer requestConsumer){
this.keyword = keyword;
this.requestConsumer = requestConsumer;
}
@Override
public void run() {
String newKeyword = keyword.toLowerCase(Locale.ROOT);
newKeyword = newKeyword.replace(' ',' ');
String url = "https://www.google.gr/search?bih=427&biw=1835&hl=el&gbv=1&tbm=isch&og=&ags=&q=" newKeyword;
try {
Document document = Jsoup.connect(url).get();
imgRealList = new ArrayList<>();
Elements imgList = document.select("img");
for (int i=1;i<imgList.size();i ) {
if(i==8)
break;
String imgSrc = imgList.get(i).absUrl("src");
InputStream input = new java.net.URL(imgSrc).openStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
imgRealList.add(bitmap);
}
// I think according to your code; the data you've requested is ready
// to deliver from now on. But attention! we post it to execute it in the UI thread
uiHandler.post(() -> requestConsumer.onRequestResult(imgRealList));
} catch (IOException e) {
e.printStackTrace();
}
}
}
addItem activity class
public class addItem extends AppCompatActivity {
LoadingDialog loadingDialog;
RecyclerView imgList;
ArrayList<Bitmap> bitmapList = new ArrayList<>();
BitmapAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
/*
/ Code Unnecessary to the problem…
*/
et_title.setOnFocusChangeListener((v, hasFocus) -> {
if(!hasFocus){
getImageLogo(et_title.getText().toString());
}
});
}
@SuppressLint("NotifyDataSetChanged")
private void getImageLogo(String serviceName){
googleRequest googleList = new googleRequest(serviceName, images -> {
// Here we get the delivered results in this callback
if(images != null) {
bitmapList.clear();
bitmapList.addAll(images);
}else {
bitmapList.clear();
}
adapter.notifyDataSetChanged();
});
googleList.start();
}
}
Note I've written it in a text editor so the code needs some function test.