Solution 1 :
Write this Part:
//wait until picture on Phone
File xaifile = new File(Environment.getExternalStorageDirectory() + "/image_from_server.jpg");
while (true){
if (xaifile.exists()){
break;
}
}
replacePicture(xaifile);
in onPostExecute
Currently You are Blocking Main Thread.
Problem :
i have following problem: I have a mobile App which, on button click (“yesbutton”) fetches data from server in an Async Task (which works fine). While that task is running, I want my app to display a Layout (framelayout), which I set to invisible at creation and which contains a textview and a Circle Progressbar. So i put the line where i set it visible into my onPreExecute method in my Asnyc task, because i read that this method will be executed on the UI Thread.
But this framelayout is only showing after my whole code has run, but not while executing.
Here is my code, I removed a chunk from it where i dont think the problem is, to make it more readable for you.
public class KeepImageActivity extends AppCompatActivity {
private static final int PORT_NO = 1234;
private String pathname;
private File imgFile;
private Button yesbutton;
private Button nobutton;
private ImageView imageView;
private FrameLayout frameLayout;
@SuppressLint("SourceLockedOrientationActivity")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_keep_image);
Intent receivedIntent = getIntent();
pathname = receivedIntent.getStringExtra(CameraActivity.EXTRA_MESSAGE);
imgFile = new File(pathname);
imageView = findViewById(R.id.imageViewID);
yesbutton = findViewById(R.id.yesbuttonID);
nobutton = findViewById(R.id.discardbuttonID);
nobutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onDiscard(pathname);
}
});
yesbutton.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onClick(View view) {
onYes();
}
});
frameLayout = findViewById(R.id.framelayout);
frameLayout.setVisibility(View.GONE);
showImage();
}
//method to show a picture in an ImageView
private void showImage() {
imgFile = new File(pathname);
Bitmap bitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
imageView.setRotation(90);
imageView.setImageBitmap(bitmap);
}
private void onDiscard(String pathname) {
//....not relevant
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void onYes() {
//doInBackground just fetches data and writes to jpg
class ConnectTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
//doing stuff (connection to server and downloading image ("image_from_server"))
}
@Override
//here my frameLayout is not being set to Visible, at least not DURING execution.
protected void onPreExecute() {
frameLayout.setVisibility(View.VISIBLE);
}
@Override
protected void onPostExecute(Void aVoid) {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
ConnectTask connect = new ConnectTask();
Void[] param = null;
//execute Async task
connect.execute(param);
//wait until picture on Phone
File xaifile = new File(Environment.getExternalStorageDirectory() + "/image_from_server.jpg");
while (true){
if (xaifile.exists()){
break;
}
}
replacePicture(xaifile);
}
//here i replace the picture/bitmap in the ImageView with another one (that just came from server)
private void replacePicture(File xaifile) {
Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/image_from_server.jpg");
imageView.setRotation(90);
imageView.setImageBitmap(bitmap);
//finished loading, I commented this line to see if my Layout would show afterwards. It does.
//frameLayout.setVisibility(View.INVISIBLE);
//delete both files, not needed anymore
xaifile.delete();
imgFile.delete();
}
//AND IT SEEMS LIKE HERE IS THE MOMENT THAT THE UPDATE TO THE UI IS SHOWN. WHY??
}
Comments
Comment posted by Titus
The
Comment posted by Washbear
@Titus alright, i changed that, I moved the “frameLayout.setVisibility(View.VISIBLE) line out of the Async task and right before the loop (so now i am even calling it from the UI Thread). But it’s still not showing…
Comment posted by Washbear
Yup that worked, thanks! But why does it not work when I put the “setVisible” line right before the loop? It should set the laout to visible since it’s called on the UI Thread AND before i go into the while(true) loop, shouldn’t it?
Comment posted by Lokesh Deshmukh
When you called Step1>connect.execute(param); //New Thread stared Right after that you called this line: Step2> File xaifile = new File(Environment.. This will execute in micro seconds and main thread is blocked. As this is on main thread. Then in your async task you called step3>frameLayout.setV.. This will execute when step2 executed completely but as file is not found loop is not going to terminate and step3 will only be called when loop finish. In your case when file is created after async task postExecute. Hope this helps!