Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android OkHttp(二)實戰

Android OkHttp(二)實戰

編輯:關於Android編程

Android OkHttp(一)初識,這篇文章最後提供了一個封裝Okhttp請求的類,今天就來看看在項目中具體的使用情況。

一、簡單接口請求。

接口請求,需要有一個服務端,這裡就使用之前用SpringMVC做的一個接口服務,接口有關的詳細開發步驟。

1.啟動接口服務後,運行後的效果截圖如下,

\

可以看到 ,接口返回的是json格式的數據,json數據定義了返回狀態、返回碼以及返回數據等

2.客戶端程序開發。

客戶端使用Android小程序去調用接口。記得加入網絡訪問請求權限

 

 

下面主要展示具體的調用,

 

public class MainActivity extends AppCompatActivity {

    private Button btn;
    private TextView tv;
    private ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.btn);
        tv = (TextView) findViewById(R.id.tv);
        iv = (ImageView) findViewById(R.id.iv);
        Log.e("Thread.currentThread()--->", Thread.currentThread().getId() + "");//打印當前線程的id
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            getAllStudent();
            }
        });
    }
}

 

MainActivity界面有Button和TextView,點擊Button去調用接口,TextView則用來顯示接口數據。下面是具體調用方法,

 

  /**
     * 獲取接口數據`
     */
    private void getAllStudent() {
        //接口返回的json
        TypeToken> typeToken = new TypeToken>() {
        };
        OkHttpUtils.getInstance().getAsyn(Constant.GET_ALL_STUDENT, null, typeToken, new BaseResponseCallback>() {
            @Override
            public void onCompleted(final Throwable e, ListResponse result) {
                if (e != null) {
                    tv.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
                } else {
                    Log.e("Thread.currentThread()--->", Thread.currentThread().getId() + "");//打印當前線程的id
                    //獲取接口返回的列表數據
                    List list = result.getItems();
                    final StringBuffer sb = new StringBuffer();
                    for (Students students : list) {
                        sb.append("姓名:" + students.getName() + ", 年齡" + students.getAge() + ", 電話" + students.getMobile()).append("\n");
                    }
                    //更新UI,在子線程中,不能直接更新UI
                    tv.post(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText(sb.toString());
                        }
                    });
                }
            }
        });
    }
在回調方法中要加入判斷請求是否成功,最後記得顯示接口數據時,不能直接在回調方法中更新UI,否則會報異常,如下圖所示,

 

\
再看下面這種截圖,

\

可以看到打印了兩個線程的id是不一樣的,一個是主線程,一個是子線程。程序運行後的效果截圖,

\

PS: 我們還可以在點擊Button時,顯示一個進度條(模態對話框),當請求結束後,關閉該進度條。這樣在請求時,有一個比較好的用戶體驗,明確告訴用戶,程序現在在做什麼!微笑

更新UI,有多種方式,還可以使用handler發消息到主線程中,讓主線程更新UI!

二、文件下載。

1.服務端。

下載一張圖片。該圖片位於Tomact服務器路徑底下。

\

啟動在Tomact服務器,然後在浏覽器中輸入圖片地址,截圖如下所示,

\

2.客戶端程序開發。

MainActivity界面有Button和ImageView,點擊Button去調用接口,ImageView則用來顯示下載的圖片。

首先記得加入讀寫sd卡權限,

 

 
    
    
    
    
下面看具體調用,

 

 

  /**
     * 下載圖片
     */
    private void downLoadPic() {
        OkHttpUtils.getInstance().downloadFileAsyn(Constant.PIC_URL, null, FileUtils.createFile(MainActivity.this, "pic", "1.png"), new BaseResponseCallback() {
            @Override
            public void onCompleted(final Throwable e, final Object result) {
                if (e != null) {
                    tv.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
                } else {
                    if (result != null) {
                        iv.post(new Runnable() {
                            @Override
                            public void run() {
                                String path = (String) result;
                                Log.e("path--->", path);
                                Bitmap bitmap = BitmapFactory.decodeFile(path);
                                iv.setImageBitmap(bitmap);
                            }
                        });
                    }
                }
            }
        });
    }

 

 

FileUtils.createFile(MainActivity.this,"pic","1.png") //是創建一個文件

點擊Button去調用下載圖片,下載完成後在ImageView中加載圖片,點擊運行後的效果如下,

\

打印出下載文件的路徑,我們在手機上去該目錄底下看看文件是否存在,

\

在目錄下,已經存在下載的文件了,下面顯示手機運行後的效果截圖,

 

\

三、文件上傳。

在調用接口上傳文件前,先做了一個JSP網頁上傳一個文件。

1. 使用form 上傳一個文件。

(1). 首先需要創建一個上傳的JSP網頁,具體代碼

 

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>

選擇文件:  
該JSP網頁功能很簡單,選擇文件,然後點擊提交。
(2).創建兩個JSP網頁,一個是成功,另外一個是失敗,用於上傳後跳轉,內容自己可以定制,我這邊只顯示文字。具體代碼就不列舉了!具體代碼詳解Demo工程。

 

(3).創建一個上傳接口,具體代碼如下,

 

public interface UpLoadFileService {
	 public boolean uploadFile(String destinationDir, MultipartFile file);
}
該接口只有一個上傳方法,下面在看該接口的實現類,

 

 

public class UploadFileServiceImpl implements UpLoadFileService {

	public boolean upload(String destinationDir, MultipartFile file) {
		return uploadFile(destinationDir, file);
	}

	/**
	 * 保存文件
	 * 
	 * @param stream
	 * @param path
	 * @param filename
	 * @throws IOException
	 */
	private void SaveFileFromInputStream(InputStream stream, String path, String filename) throws IOException {
		FileOutputStream outputStream = new FileOutputStream(path + "/" + filename);
		int byteCount = 0;
		byte[] bytes = new byte[1024];
		while ((byteCount = stream.read(bytes)) != -1) {
			outputStream.write(bytes, 0, byteCount);
		}
		outputStream.close();
		stream.close();
	}

	@Override
	public boolean uploadFile(String destinationDir, MultipartFile file) {
		StringBuffer sb = new StringBuffer();
		sb.append("文件長度: " + file.getSize());
		sb.append("文件類型: " + file.getContentType());
		sb.append("文件名稱: " + file.getName());
		sb.append("文件原名: " + file.getOriginalFilename());
		System.out.println(sb.toString());
		try {
			SaveFileFromInputStream(file.getInputStream(), destinationDir, file.getOriginalFilename());
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

}
該實現類,將文件流寫入到具體目錄中,和我們第二部的下載文件很類似。
(4).接著定義個Action,提供外部調用接口,

 

 

@Controller
public class UpLoadFileServlet {

	@RequestMapping(value = "/upLoadFile.dbo", method = RequestMethod.POST)
	public ModelAndView getAllStudent(HttpServletRequest request, HttpServletResponse response,
			 ModelMap modelMap) {
		 // 轉型為MultipartHttpRequest:     
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;     
        // 獲得文件:     
        MultipartFile file = multipartRequest.getFile("file"); 
		String realPath = "D:/java_web/upload";//文件存放路徑,需要首先創建
		boolean result = false;
		result = UploadFileBusiness.upload(realPath, file);
		String resultJsp = "";
		SingleObject singleObject = new SingleObject();
		if (result) {
			resultJsp = "uploadFileSuccess";
			singleObject.setCode(StatusCode.CODE_SUCCESS);
			singleObject.setMsg("上傳成功");
		} else {
			resultJsp = "uploadFileFail";
			singleObject.setCode(StatusCode.CODE_ERROR);
			singleObject.setMsg("上傳失敗");
		}
		singleObject.setObject("");
		modelMap.addAttribute("result", singleObject);
		return new ModelAndView(resultJsp, modelMap);
	}
}

上傳文件調用了UploadFileBusiness.upload()方法,

 

 

public class UploadFileBusiness {
	
	/**
	 * 上傳文件
	 * @param destinationDir
	 * @param file
	 * @return
	 */
	public static boolean upload(String destinationDir, MultipartFile file) {
		return new UploadFileServiceImpl().upload(destinationDir, file);
	}

}

 

 

(5).最後記得要在springmvc.xml中配置過濾器,

 




	
	
	
	
	
	
	
	
	
	
		
		
		
	
	...
	
	
	
		
			
				
				error_fileupload
			
		
	
	...

因為需要上傳文件,所以還要導入幾個jar包才可以,commons-fileupload-*.jar和commons-io-*.jar等包。

此致,上傳功能已經完成了!下面展示一張,項目截圖,

\

最後運行,效果截圖如下,選擇文件,點擊提交,

\

點擊提交後,如果上傳成功,會跳轉至上傳成功(uploadFileSuccess.jsp),並且在管理端打印了該文件的信息,

\

我們去上傳文件的保存目錄(D:/java_web/upload)看看是否有上傳文件,

\

點擊提交後,如果上傳失敗,會跳轉至上傳失敗(uploadFileFail.jsp),在控制台會輸出上傳失敗原因,便於大家分析出錯原因。

\

2.客戶端調用接口上傳文件。

在Android設備上,選擇一張圖片,上傳至後台。

(1). 選擇圖片,

 

  /**
     * 選擇圖片
     */
    private void selectPic() {
        Intent intent = new Intent();
        if (Build.VERSION.SDK_INT < 19) {//因為Android SDK在4.4版本後圖片action變化了 所以在這裡先判斷一下
            intent.setAction(Intent.ACTION_GET_CONTENT);
        } else {
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        }
        intent.setType("image/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        startActivityForResult(intent, PICTURE);
    }
回調處理,

 

 

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (data == null) {
            return;
        }
        Uri uri = data.getData();
        switch (requestCode) {
            case PICTURE:
                String imagePath = FileUtils.getUriPath(this, uri); //(因為4.4以後圖片uri發生了變化)通過文件工具類 對uri進行解析得到圖片路徑
                if (!TextUtils.isEmpty(imagePath)) {
                    uploadFile(imagePath);
                }
                break;
            default:
                break;
        }
    }
上傳文件,

 

 

  /**
     * 文件上傳
     *
     * @param filePath
     */
    private void uploadFile(String filePath) {
        File file = new File(filePath);
        TypeToken> typeToken = new TypeToken>() {
        };
        OkHttpUtils.getInstance().postAsyn(Constant.UPLOAD_PIC_URL, null, file,"file",typeToken, new BaseResponseCallback>() {

            @Override
            public void onCompleted(final Throwable e, EntityResponse result) {
                if (e != null) {
                    tv.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    });
                } else {
                    //獲取接口返回的列表數據
                   Image image = result.getObject();
                    final StringBuffer sb = new StringBuffer();
                    sb.append("文件名稱:" + image.getName() + ", 下載地址:" + image.getUrl() );
                    //更新UI,在子線程中,不能直接更新UI
                    tv.post(new Runnable() {
                        @Override
                        public void run() {
                            tv.setText(sb.toString());
                        }
                    });
                }
            }
        });
    }
客戶端運行截圖,首先選擇圖片,

 

\

選擇完成後,上傳成功返回json數據截圖,

\

上傳成功截圖,

\

再看看服務端截圖,控制台輸入日志截圖,

\

然後打開上傳文件目錄,

\

上傳文件也OK了!

四、總結

本文主要是基於封裝Okhttp請求的類調用後台服務接口,實現不同的功能!經測試,該類基本滿足功能!本文對上篇文章封裝的Okhttp請求類有所優化,更加詳細的代碼,請看本篇的例子工程源代碼!本文需要有點Okhttp和SpringMVC方面的知識!

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved