您的位置:首页 > 移动开发 > Android开发

Android:仿微博Listview与多线程功能(JSON、数据下载、图片加载、Listview、异步任务)

2013-06-03 20:22 711 查看
解析服务端JSON的内容和图片,通过异步任务下载并设置到listview页上,点击listview跳转到详情页。
public class WatchingActivity extends Activity implements OnClickListener, OnItemClickListener
{
private ListView mListView;
private HashMap<URL, Bitmap> mCacheMap = new HashMap<URL, Bitmap>();
private View errorView;
private View loadingview;
private RelativeLayout errorlayout;
private Button btn_netRetry;
private View headview;
private View footview;
private View btn_footviewloading;
private TextView btn_loadmore;
private int mPage = 1;
private BaseAdapter mAdapter;
private ArrayList<ItemData> mDataList = new ArrayList<ItemData>();
private View headviewad;
private View imageBtn_refresh;

/*
* 创建布局
* 下载内容
* 解析内容
* 下载图片
* 图片缓存
* 网络错误页面
* 网络加载页面
* 增加页眉
* 加载更多
* 页眉响应
* ListView行跳转
* 内容页显示详情
*/

/**
* 1.适配器判断是否为空,生命周期?还是因为是第一次===========> 复用会导致数据重新刷新,不能在原有数据基础上加载
* 2.页眉整张图片,则无法直接点击------------------->layout拦截掉了监听
* 3.加载更多链接不在时result会报错空值--------------->
* 4.mListView.setOnItemClickListener(this);用这个方法监听ListView无效?========>监听行布局对象
* 5.顶部刷新按钮为何不响应?
* 6.行布局的进度条为何找不到?========>已解决
* 7.include移位就报错==============>没问题
* 8.控件层次如何改变=============> relative根据xml代码位置
* 9.setonItemClick  position要减1才能对应?============> 加完headview后,position初始值自动加1
*
*/

class ItemData
{
String imageUrl;
String title;
String from;
String time;
String content;
public ItemData(String imageUrl, String title, String from,
String time, String content)
{
super();
this.imageUrl = imageUrl;
this.title = title;
this.from = from;
this.time = time;
this.content = content;
}

}

class ViewHolder
{
ImageView imageView;
TextView textView_title;
TextView textView_from;
TextView textView_time;

ProgressBar progressBar_imageLoading;
}

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_watching);

setUI();

}
private void setUI()
{
LayoutInflater inflater = getLayoutInflater();
headview = inflater.inflate(R.layout.headview, null);
footview = inflater.inflate(R.layout.footview, null);
btn_footviewloading = footview.findViewById(R.id.footview_loading);
btn_loadmore = (TextView) footview.findViewById(R.id.btn_loadmore);
headviewad = headview.findViewById(R.id.imageView_headview_ad);
imageBtn_refresh = findViewById(R.id.imageBtn_refresh);

btn_netRetry = (Button) findViewById(R.id.btn_netRetry);
loadingview = findViewById(R.id.loadingview);
errorView = findViewById(R.id.errorview);
mListView = (ListView) findViewById(R.id.listView_watching);
mListView.addHeaderView(headview);//注意:一定要在setAdapter之前调用,所以一般在找到listview之后就添加
mListView.addFooterView(footview);

loadTask();

//网络连接重试按钮
btn_netRetry.setOnClickListener(this);
//分页加载更多
btn_loadmore.setOnClickListener(this);
//点击ListView页眉广告
headviewad.setOnClickListener(this);
//点击顶部刷新页面
btn_netRetry.setOnClickListener(this);
//点击listview跳转
mListView.setOnItemClickListener(this);
}

//按钮点击事件
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.btn_netRetry:
errorView.setVisibility(View.GONE);
mPage = 1;
loadTask();
break;

case R.id.btn_loadmore:
btn_loadmore.setVisibility(View.INVISIBLE);
btn_footviewloading.setVisibility(View.VISIBLE);
loadTask();
break;

case R.id.imageView_headview_ad:
Toast.makeText(WatchingActivity.this, Contant.HEADVIEW_TOAST, Toast.LENGTH_LONG).show();
break;

case R.id.imageBtn_refresh:
loadTask();
break;

default:
break;
}
}

//监听listview
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id)
{
if(view.getId() == R.id.watching_item)//监听的对象是行布局
{
Intent intent = new Intent(WatchingActivity.this, ContentActivity.class);
ItemData data = mDataList.get(position - 1);
String fromtime = data.from +" " + Contant.TIME_YEAR + data.time;
intent.putExtra(Contant.KEY_INTENTER_TITLE, data.title);
intent.putExtra(Contant.KEY_INTENTER_FROMTIME, fromtime);
intent.putExtra(Contant.KEY_INTENTER_CONTENT, data.content);
startActivity(intent);
}
}

//启动异步任务
private void loadTask()
{
URL dataUrl = null;
try
{
dataUrl = new URL(Contant.URL_DATA + mPage + Contant.URL_DATA_FILEFORM);
// 异步任务下载数据
LoadDataTask loadDataTask = new LoadDataTask();
loadDataTask.execute(dataUrl);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
}

// 异步任务下载数据
class LoadDataTask extends AsyncTask<URL, Void, String>
{
@Override
protected void onPreExecute()
{
loadingview.setVisibility(View.VISIBLE);
}
@Override
protected String doInURL...  params)
{
InputStream is = null;
ByteArrayBuffer strBuf = new ByteArrayBuffer(59658);//使用ByteArrayBuffer,直接使用String可能造成读取到的部分内容乱码
try
{
HttpURLConnection conn = (HttpURLConnection) params[0].openConnection();
conn.setConnectTimeout(Contant.HTTP_TIME_OUT);
conn.setReadTimeout(Contant.HTTP_TIME_OUT);
// 判断网络连接是否正常
if(conn.getResponseCode() != HttpURLConnection.HTTP_OK)
{
//返回错误提示页面
return null;
}

// 下载数据
is = conn.getInputStream();
byte[] buf = new byte[1024];
int len = 0;

while (-1 != (len = is.read(buf)))
{
strBuf.append(buf, 0, len);//直接加入ByteArrayBuffer
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return new String(strBuf.buffer());//bytebuffer数组转成字符串
}

// 下载数据解析,更新控件内容
@Override
protected void onPostExecute(String result)
{
loadingview.setVisibility(View.GONE);

//判断result是否为空
if(TextUtils.isEmpty(result.trim()))
{
btn_loadmore.setVisibility(View.GONE);
errorView.setVisibility(View.VISIBLE);
mListView.setVisibility(View.GONE);
// return;
}
else
{
btn_loadmore.setVisibility(View.VISIBLE);
btn_footviewloading.setVisibility(View.INVISIBLE);
mListView.setVisibility(View.VISIBLE);
// 解析json数据
ArrayList<ItemData> dataList = parse(result);
//更新控件内容
setListData(dataList);

}
}
}

//更新行内容
private void setListData(ArrayList<ItemData> dataList)
{
//判断mAdapter是否为空,复用mAdapter实现内容加载,重新set会导致所有内容重新加载(跳到第一行)
if(null == mAdapter)
{
createAdapter(dataList);//创建适配器
mListView.setAdapter(mAdapter);
}
else
{
mAdapter.notifyDataSetChanged();//通知listview更新界面
}
}

// 解析json数据
private ArrayList<ItemData> parse(String result)
{
try
{
JSONArray jsonArray = new JSONArray(result);
mPage++;//数据解析完成后,页数修改
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObject = jsonArray.getJSONObject(i);
String imageUrl = Contant.URL_HOST + jsonObject.getString(Contant.KEY_JSON_IMGURL);
String title = jsonObject.getString(Contant.KEY_JSON_TITLE);
String from = jsonObject.getString(Contant.KEY_JSON_FROM);
String time = jsonObject.getString(Contant.KEY_JSON_TIME);
String content = jsonObject.getString(Contant.KEY_JSON_CONTENT);
ItemData itemData = new ItemData(imageUrl, title, from, time,content);
mDataList.add(itemData);
}
}
catch (JSONException e)
{
e.printStackTrace();
}
return mDataList;
}

//创建Adapter,设置LiseView
private void createAdapter(final ArrayList<ItemData> dataList)
{
mAdapter = new BaseAdapter()
{
@Override
public View getView(int position, View convertView,ViewGroup parent)
{
ViewHolder holder;
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.watch_layout, null);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.imgView_watch_newspic);
holder.textView_title = (TextView) convertView.findViewById(R.id.txtView_watch_title);
holder.textView_from = (TextView) convertView.findViewById(R.id.txtView_from);
holder.textView_time = (TextView) convertView.findViewById(R.id.txtView_time);
holder.progressBar_imageLoading = (ProgressBar) convertView.findViewById(R.id.progressBar_imageloading);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}

ItemData itemData = dataList.get(position);

//启动图片下载任务
try
{
URL url = new URL(itemData.imageUrl);
if(mCacheMap.containsKey(url))
{
holder.imageView.setImageBitmap(mCacheMap.get(url));
}
else
{
LoadImageTask imageTask = new LoadImageTask(holder.imageView,holder.progressBar_imageLoading);
imageTask.execute(url);
}
}
catch (MalformedURLException e)
{
e.printStackTrace();
}

holder.textView_title.setText(itemData.title);
holder.textView_from.setText(itemData.from);
holder.textView_time.setText(itemData.time);
return convertView;
}

@Override
public long getItemId(int position)
{
return 0;
}

@Override
public Object getItem(int position)
{
return null;
}

@Override
public int getCount()
{
return dataList.size();
}
};
}

//下载图片
class LoadImageTask extends AsyncTask<URL, Void, Bitmap>
{
private ImageView imageView;
ProgressBar progressBar_imageLoading;
public LoadImageTask(ImageView imageView, ProgressBar progressBar_imageLoading)
{
this.imageView = imageView;
this.progressBar_imageLoading = progressBar_imageLoading;
}

@Override
protected void onPreExecute()
{
progressBar_imageLoading.setVisibility(View.VISIBLE);
}

//下载图片
@Override
protected Bitmap doInURL...  params)
{
InputStream is = null;
Bitmap bitmap = null;
try
{
//判断网络连接
HttpURLConnection conn = (HttpURLConnection) params[0].openConnection();
conn.setConnectTimeout(Contant.HTTP_TIME_OUT);
conn.setReadTimeout(Contant.HTTP_TIME_OUT);
if(conn.getResponseCode() != HttpURLConnection.HTTP_OK)
{
return null;
}

//由url获取bitmap对象
is = conn.getInputStream();  //简写方法:is = params[0].openStream()
bitmap = BitmapFactory.decodeStream(is);
mCacheMap.put(params[0], bitmap);
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(null != is )
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return bitmap;
}

@Override
protected void onPostExecute(Bitmap bitmap)
{
if(bitmap == null)
{
//图片加载失败
}
else
{
progressBar_imageLoading.setVisibility(View.INVISIBLE);
imageView.setImageBitmap(bitmap);
}
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.watching, menu);
return true;
}
}


其他优化和扩展:
1.图片加载 与设置图片方法一样,将控件对象传到异步任务里
2.惰性加载

其他相关:
1.隐藏headview
<LinearLayout android:id="@+id/item_root"
android:layout_width="fill_parent"
android:layout_height="50dip"
android:orientation="vertical" >
<LinearLayout android:id="@+id/item_container"
<TextView  android:id="@+id/tv_1" />
<TextView  android:id="@+id/tv_2" />
</LinearLayout>
</LinearLayout >
要隐藏的view必须不能是根目录的view的id。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐