我是新开发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