我是新開發Android應用程序,在學校只有一點Java經驗。當我正在查找Android Beginners組時,我被重定向到Google組頁面的StackOverflow。我有一個問題,關於什麼是從Web源中獲取內容並解析它的最佳實踐。首先,我最終希望讓我的應用程序通過線程(通過使用Handler?),但是,現在我的問題是,我創建的(服務器)類連接和獲取內容通常無法檢索內容,這會導致我的JSON解析器類(JSONParser)失敗,並且我的視圖不顯示任何內容。在導航到前一個Activity後,嘗試在同一個遠程URI上調用connect(),fetch()和parse()方法後,它就可以工作。從網絡提取內容的最佳做法?
這是爲什麼(有時檢索遠程數據)發生有時,但並非總是如此?最佳做法是什麼,包括使用ProgressDialog和內部Handler類,以使我的應用程序與用戶無縫連接。這是問這個問題的最佳地點嗎?感謝您的幫助
這是我現在使用的代碼。
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import org.apache.http.util.ByteArrayBuffer;
import android.util.Log;
public class Server {
public static final String HTTP_PROTOCOL = "https://";
public static final String EXAMPLE_NET_DOMAIN = "example.domain.net/";
private final String API_KEY = "1234567890";
private static final String API_ENDPOINT = "api.js?";
public final String FORMAT = "json";
public String API_VERSION;
public String METHOD;
public String OPTIONAL_ARGUMENTS;
public String json;
public URL jURL;
public URLConnection jConnection;
public BufferedReader jIn;
public InputStream is = null;
/**
* @param aPIVERSION
* @param mETHOD
* @param oPTIONALARGUMENTS
*/
public Server(String aPIVERSION, String mETHOD, String oPTIONALARGUMENTS) {
super();
API_VERSION = aPIVERSION;
METHOD = mETHOD;
OPTIONAL_ARGUMENTS = oPTIONALARGUMENTS;
connect();
Log.i("DEBUG:","connect();");
}
/**
* @param aPIVERSION
* @param mETHOD
*/
public Server(String aPIVERSION, String mETHOD) {
super();
API_VERSION = aPIVERSION;
METHOD = mETHOD;
OPTIONAL_ARGUMENTS = "";
connect();
}
/**
* @param aPIVERSION
* @param mETHOD
*/
public void connect(){
try {
jURL = new URL(HTTP_PROTOCOL
+ EXAMPLE_NET_DOMAIN
+ API_ENDPOINT
+ "api=" + this.API_VERSION
+ "&method=" + this.METHOD
+ "&format=" + FORMAT
+ "&apikey=" + API_KEY
+ this.OPTIONAL_ARGUMENTS);
jConnection = jURL.openConnection();
} catch (IOException e) {
Log.e("USER: ", "Error in server connection.");
Log.e("DEBUG:", "Error in server connection");
}
Log.i("USER: ", "Connection success!");
}
public String fetch() {
try {
is = jConnection.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("DEBUG:", "fetch-1() error");
}
BufferedInputStream bis = new BufferedInputStream(is);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
try {
while((current = bis.read()) != -1){
baf.append((byte)current);
}
Log.i("DEBUG:",new String(baf.toByteArray()));
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("DEBUG:","fetch() ERROR!");
}
/* Convert the Bytes read to a String. */
Log.i("DEBUG:",new String(baf.toByteArray()));
return new String(baf.toByteArray());
}
/* Returns a string containing a concise, human-readable description of jURL
*
*/
public String showUrl() {
return jURL.toExternalForm();
}
}
,並從我的ListActivity
/* Called when the activity is starting. This is where most initialization should go: calling setContentView(int) to inflate the activity's UI, using findViewById(int) to programmatically interact with widgets in the UI, calling managedQuery(android.net.Uri, String[], String, String[], String) to retrieve cursors for data being displayed, etc.
* @see android.app.Activity#onCreate()
*/
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.i("LIFECYCLE: ", "RS.class onCreate()");
Server serverConnection = new Server(API_VERSION, METHOD, OPTIONAL_ARGUMENTS);
json = serverConnection.fetch();
JSONParser jParser = new JSONParser(json);
groupData = jParser.parseJsonForRecentShowList();
SimpleAdapter adapter = new SimpleAdapter(this, groupData, android.R.layout.simple_list_item_2, new String[] { "venue","showdate"},
new int[]{ android.R.id.text2, android.R.id.text1 });
setListAdapter(adapter);
registerForContextMenu(getListView());
}
下面的代碼是我的JSON解析器類
/**
*
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
/**
* @author
*
*/
public class JSONParser {
public List<Map<String, String>> groupData = new ArrayList<Map<String, String>>();
private String jString;
private Map<String, String> group;
private JSONArray jArray;
private String setlistData;
public String notesString = "";
public String[] splitSetsArray;
public String[] splitEncoreArray;
public String[] extraWork;
public String[] notesArray;
public String pVenue_text;
public String pCity_text;
public String pState_text;
public String pCountry_text;
public String pDate_text;
public String pSet1_text;
public String pSet2_text;
public String pSet3_text;
public String pEncore1_text;
public String pEncore2_text;
public String pNotes_text;
public int totalNumberOfSets;
public int totalNumberOfEncores;
public int totalNumberOfNotes;
public JSONObject jObject;
public JSONParser(String json) {
// TODO Auto-generated constructor stub
jString = json;
}
/**
* @return
*/
public List<Map<String, String>> parseJsonForRecentShowList(){
try {
jArray = new JSONArray(jString);
for(int i=0;i<jArray.length();i++) {
jObject = jArray.getJSONObject(i);
group = new HashMap<String, String>();
group.put("showdate", jObject.getString("showdate"));
group.put("venue", jObject.getString("venue"));
groupData.add(group);
}
} catch (JSONException e) {
Log.e("DEBUG: ", "JSON Parse error!");
}
return groupData;
}
/**
*
*/
public void parseJsonForSetlistData(){
if(jString != null){
try {
jArray = new JSONArray(jString);
jObject = jArray.getJSONObject(0);
pVenue_text = jObject.getString("venue") ;
pCity_text = jObject.getString("city") + ", " ;
pState_text = jObject.getString("state") + ", " ;
pCountry_text = jObject.getString("country") ;
pDate_text = jObject.getString("nicedate") ;
setlistData = nohtml(jObject.getString("setlistdata"));
splitSetsArray = setlistData.split("Set..:.");
totalNumberOfSets = splitSetsArray.length-1;
String[] splitEncoreArray = splitSetsArray[splitSetsArray.length-1].split("Encore:.");
totalNumberOfEncores = splitEncoreArray.length-1;
splitSetsArray[splitSetsArray.length-1] = splitEncoreArray[0];
splitEncoreArray[0] = "";
extraWork = splitEncoreArray[splitEncoreArray.length-1].split("\\[1\\]");
notesArray = extraWork[extraWork.length-1].split("\\[.\\]");
totalNumberOfNotes = notesArray.length-1;
splitEncoreArray[splitEncoreArray.length-1] = extraWork[0];
//notesArray[0] = "";
for(int i=0;i<notesArray.length;i++){
int number = i+1;
notesString += "["+number+"] "+notesArray[i] + "\n";
}
if(totalNumberOfSets != 0) {
pSet1_text = "Set 1: " + splitSetsArray[1];
if (totalNumberOfSets > 1){
pSet2_text = "Set 2: " + splitSetsArray[2];
} else {
pSet2_text = "";
}
if (totalNumberOfSets > 2){
pSet3_text = "Set 3: " + splitSetsArray[3];
} else {
pSet3_text = "";
}
}
pEncore1_text = "Encore: " + splitEncoreArray[1];
if (totalNumberOfEncores > 1) {
pEncore2_text = "Encore 2: " + splitEncoreArray[2];
} else {
pEncore2_text = "";
}
pNotes_text = notesString;
Log.e("DEBUG: ", "JSON Parsed!");
} catch (JSONException e) {
Log.e("ERROR:","caught JSON Exception at parseForSetlistData()");
}
} else {
Log.e("ERROR:", "jString = null");
pVenue_text = "I'm Sorry, the Setlist Data could not be retrieved from server. Please try again.";
}
}
public void parseJsonForReviews(){
try {
jArray = new JSONArray(jString);
for(int i=0;i<jArray.length();i++){
jObject = jArray.getJSONObject(i);
group = new HashMap<String, String>();
group.put("author", jObject.getString("author"));
group.put("review", jObject.getString("review"));
groupData.add(group);
}
} catch (JSONException e) {
Log.e("DEBUG: ", "JSON Reviews parse error!");
}
}
public List<Map<String, String>> parseJsonForYears(){
try {
jArray = new JSONArray(jString);
for(int i=0;i<jArray.length();i++){
JSONObject jObject = jArray.getJSONObject(i);
group = new HashMap<String, String>();
group.put("showdate", jObject.getString("showdate"));
group.put("venue", jObject.getString("venue"));
groupData.add(group);
}
} catch (JSONException e) {
Log.e("DEBUG: ", "JSON Years parse error!");
}
Collections.reverse(groupData);
return groupData;
}
public String nohtml(String json){
return json.toString().replaceAll("\\<.*?>", "");
}
}
感謝您的輸入反應。我在Eclipse和Android DDMS中使用過,問題是「new String(baf.toByteArray())」返回的字符串是空的。這幾乎就像數據檢索失敗一樣,所以方法放棄了,並返回一個空字符串,這導致我的解析器失敗並且我的視圖沒有被填充。 AndroidHttpClient聽起來很有希望。我會嘗試這一點,並希望獲得更好的結果。 – 2010-09-30 01:20:42
其他警告/錯誤怎麼樣?它們是否在logcat中顯示? – bhups 2010-09-30 04:06:11
在我的設備上運行時,我會看到與WifiService(acquireWifiLockedLock)和LocationMasfClient(getNetworkLocation)相關的藍色系統消息,我不認爲這與錯誤有任何關係。 我無法一致地重現錯誤。在設備上測試期間,錯誤(空字符串)似乎在更長時間的網絡活動(第一次啓動應用程序,或幾分鐘不使用等)之後發生,並且在高活動期間發生_less_ (儘可能快地測試/啓動設備上的查詢)。 – 2010-09-30 04:23:50