有时给我跳过57帧!应用程序可能在其主线程上做了太多的工作


Sometimes give me Skipped 57 frames! The application may be doing too much work on its main thread

我有这段代码用于将图像从android发送到服务器,它很有效!但有时它会让我回想起logcat中的一个错误:

Skipped 57 frames! The application may be doing too much work on its main thread

但我不知道只是有时,例如,当这种情况发生时,安装该应用程序的手机工作不好!

public class SendingImage extends Activity {
        private static final int REQUEST_IMAGE = 100;   
        TextView tvPath;
        TextView txtHaut;
        ImageView preview;
        File destination;
        String imagePath;
        ImageButton takePhoto;
        Button btnCreate;
        int serverResponseCode = 0;
        ProgressDialog dialog = null;
        String upLoadServerUri = null;
        String name;       
        private static final int CAMERA_REQUEST = 1;
        private static final int PICK_FROM_GALLERY = 2;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_sending_image);
            preview = (ImageView) findViewById(R.id.imageViewPreview);
            btnCreate = (Button) findViewById(R.id.bInviaFoto) ;
            txtHaut = (TextView) findViewById(R.id.textViewEsito);
            takePhoto = (ImageButton) findViewById(R.id.bCamera);
            preview.setVisibility(View.GONE);
            txtHaut.setVisibility(View.GONE);
            upLoadServerUri = "http://fiezzo.altervista.org/upload_image.php";
            name = dateToString(new Date(),"yyyyMMddhhmmss");
            destination = new File(Environment.getExternalStorageDirectory(), name + ".jpg");

            takePhoto.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
                    startActivityForResult(intent, REQUEST_IMAGE);
                }
            }); 

            btnCreate.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog = ProgressDialog.show(SendingImage.this, "", "Uploading file...", true);
                    new Thread(new Runnable() {
                        public void run() {              
                            uploadFile(imagePath);
                        }
                    }).start();        
                }
            }); 

        }

        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            if( requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK ){
                try {
                    preview.setVisibility(View.VISIBLE);
                    takePhoto.setVisibility(View.GONE);
                    txtHaut.setVisibility(View.VISIBLE);
                    txtHaut.setText("Immagine selezionata correttamente!");
                    FileInputStream in = new FileInputStream(destination);
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inSampleSize = 15;
                    imagePath = destination.getAbsolutePath();
                    Log.d("INFO", "PATH === " +imagePath);
                    //tvPath.setText(imagePath);
                    Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
                    preview.setImageBitmap(bmp);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
            else{
                tvPath.setText("Request cancelled");
            }
        }

        /**
         * open camera method
         */
        public void callCamera() {
            Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            cameraIntent.putExtra("crop", "true");
            cameraIntent.putExtra("aspectX", 0);
            cameraIntent.putExtra("aspectY", 0);
            cameraIntent.putExtra("outputX", 200);
            cameraIntent.putExtra("outputY", 150);
            startActivityForResult(cameraIntent, CAMERA_REQUEST);
        }
        /**
         * open gallery method
         */
        public void callGallery() {
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.putExtra("crop", "true");
            intent.putExtra("aspectX", 0);
            intent.putExtra("aspectY", 0);
            intent.putExtra("outputX", 200);
            intent.putExtra("outputY", 150);
            intent.putExtra("return-data", true);
            startActivityForResult(
                    Intent.createChooser(intent, "Complete action using"),
                    PICK_FROM_GALLERY);
        }
        public String dateToString(Date date, String format) {
            SimpleDateFormat df = new SimpleDateFormat(format);
            return df.format(date);
        }
        public int uploadFile(String sourceFileUri) {
            String fileName = sourceFileUri;
            HttpURLConnection conn = null;
            DataOutputStream dos = null;  
            String lineEnd = "'r'n";
            String twoHyphens = "--";
            String boundary = "*****";
            int bytesRead, bytesAvailable, bufferSize;
            byte[] buffer;
            int maxBufferSize = 1 * 1024 * 1024; 
            File sourceFile = new File(sourceFileUri); 
            if (!sourceFile.isFile()) {
                dialog.dismiss(); 
                Log.e("uploadFile", "Source File not exist :" +imagePath);
                return 0;
            } else {
                try { 
                    // open a URL connection to the Servlet
                    FileInputStream fileInputStream = new FileInputStream(sourceFile);
                    URL url = new URL(upLoadServerUri);
                    // Open a HTTP  connection to  the URL
                    conn = (HttpURLConnection) url.openConnection(); 
                    conn.setDoInput(true); // Allow Inputs
                    conn.setDoOutput(true); // Allow Outputs
                    conn.setUseCaches(false); // Don't use a Cached Copy
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Connection", "Keep-Alive");
                    conn.setRequestProperty("ENCTYPE", "multipart/form-data");
                    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                    conn.setRequestProperty("uploaded_file", fileName); 
                    dos = new DataOutputStream(conn.getOutputStream());
                    dos.writeBytes(twoHyphens + boundary + lineEnd); 
                    dos.writeBytes("Content-Disposition: form-data; name='"uploaded_file'";filename="+ fileName + "" + lineEnd);
                    dos.writeBytes(lineEnd);
                    // create a buffer of  maximum size
                    bytesAvailable = fileInputStream.available(); 
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    buffer = new byte[bufferSize];
                    // read file and write it into form...
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);  
                    while (bytesRead > 0) {
                        dos.write(buffer, 0, bufferSize);
                        bytesAvailable = fileInputStream.available();
                        bufferSize = Math.min(bytesAvailable, maxBufferSize);
                        bytesRead = fileInputStream.read(buffer, 0, bufferSize);   
                    }
                    // send multipart form data necesssary after file data...
                    dos.writeBytes(lineEnd);
                    dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
                    // Responses from the server (code and message)
                    serverResponseCode = conn.getResponseCode();
                    String serverResponseMessage = conn.getResponseMessage();
                    Log.i("uploadFile", "HTTP Response is : "+ serverResponseMessage + ": " + serverResponseCode);
                    if(serverResponseCode == 200){
                        runOnUiThread(new Runnable() {
                            public void run() {
                                Toast.makeText(SendingImage.this, "File Upload Complete.", Toast.LENGTH_SHORT).show();
                            }
                        });                
                    }    
                    //close the streams //
                    fileInputStream.close();
                    dos.flush();
                    dos.close();
                } catch (MalformedURLException ex) {
                    dialog.dismiss();  
                    ex.printStackTrace();
                    runOnUiThread(new Runnable() {
                        public void run() {
                            Toast.makeText(SendingImage.this, "MalformedURLException",  Toast.LENGTH_SHORT).show();
                        }
                    });
                    Log.e("Upload file to server", "error: " + ex.getMessage(), ex);  
                } catch (Exception e) {
                    dialog.dismiss();  
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        public void run() {
                            Toast.makeText(SendingImage.this, "Got Exception : see logcat ", Toast.LENGTH_SHORT).show();
                        }
                    });
                    Log.e("Upload file to server Exception", "Exception : " + e.getMessage(), e);  
                }
                dialog.dismiss();   
                return serverResponseCode; 
            } // End else block 
        } 
    }

这也是php代码:

<?php
    $file_path = "uploads/";
    $file_path = $file_path . basename( $_FILES['uploaded_file']['name']);
    if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path)) {
        echo "success";
    } else{
        echo "fail";
    }
 ?>

我以这个项目为例:http://androidexample.com/Upload_File_To_Server_-_Android_Example/index.php?view=article_discription&aid=83&aaid=106

非常感谢您的帮助或建议!

看起来就像是在为上传本身启动一个新线程,这很好。但是这个比特

Bitmap bmp = BitmapFactory.decodeStream(in, null, options);

正在主线程上执行。你应该考虑把它移到背景中,这样你就不会在主线程上读取图像。这可能是你的问题。

更普遍地说,考虑使用AsyncTask来做这些事情:它比创建和管理自己的线程更灵活,也更不容易出错。

它还有一些东西可以让你在后台工作完成后在主线程上做一些事情。因此,使用Bitmap,您可以在doInBackground()方法中进行加载和decodeStream()调用,这发生在后台线程上;然后是下一行

preview.setImageBitmap(bmp);

是您在onPostExecute()中要做的,它(自动)发生在主线程上,因为您必须在主线程中与GUI组件交互。