Android 选项卡式视图直到触摸才会更新
Android Tabbed View Not Updating Until Touch
我有一个 android 应用程序,它的选项卡式布局包含一个列表视图。从服务器检索信息后,我正在尝试更新列表。但是,在触摸屏幕之前,列表不会更新。所有信息都是正确的,但无论我等多久,列表都不会显示在屏幕上,直到我点击它。有谁知道如何解决这个问题?
Tab1.java
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by hp1 on 21-01-2015.
*/
//NEW
public class Tab1 extends Fragment {
MainActivity mainActivity;
List<Post> postList;
public static NewAdapter newAdapter;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
@Override
public void onStart() {
super.onStart();
postList = new ArrayList<Post>();
try {
//get data from azure
mainActivity = (MainActivity) getActivity();
//set lists
ListView newListView = (ListView) mainActivity.findViewById(R.id.newListView);
newAdapter = new NewAdapter(mainActivity, postList);
newListView.setAdapter(newAdapter);
}catch(Exception e){
}
//get the posts loaded asynchronously
retrievePosts();
}
public void retrievePosts(){
AsyncTask<Void,Void,Void> task = new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
Log.e("TAG",postList.get(0).text);
newAdapter.updateList(postList);
} catch (final Exception e) {
}
return null;
}
};
runAsyncTask(task);
}
private AsyncTask<Void, Void, Void> runAsyncTask(AsyncTask<Void, Void, Void> task) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
return task.execute();
}
}
}
NewAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class NewAdapter extends BaseAdapter {
List<Post> postList;
Context context;
LayoutInflater inflater;
public NewAdapter(MainActivity mainActivity, List<Post> myPostList) {
postList=myPostList;
context=mainActivity;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return postList.size();
}
@Override
public Object getItem(int position) {
return postList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
PostCell postCell=new PostCell();
View cellView = inflater.inflate(R.layout.post_cell, null);
postCell.textView=(TextView) cellView.findViewById(R.id.textView1);
postCell.textView.setText(postList.get(position).text);
cellView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "You Clicked "+postList.get(position).text, Toast.LENGTH_LONG).show();
}
});
return cellView;
}
public List<Post> updateList(List<Post> myPostList){
postList = myPostList;
notifyDataSetChanged();
return postList;
}
public List<Post> addToList(Post post){
postList.add(post);
notifyDataSetChanged();
return postList;
}
}
编辑:最终答案 - 这是我解决问题的最终代码。 Bnydev 对这个问题的看法是正确的,但我还需要更改一些其他内容。
public void retrievePosts(){
//NOTE: must have a return type for an async task to run onpostexecute, which
//is executed on the ui thread so the screen can be updated
AsyncTask<Void,Void,Boolean> task = new AsyncTask<Void,Void,Boolean>(){
@Override
protected Boolean doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
} catch (final Exception e) {
e.printStackTrace();
}
return true;
}
protected void onPostExecute(Boolean reult) {
newAdapter.updateList(postList);
}
};
task.execute();
}
在 Tab1.java 中,您有方法 retrievePosts()
,其中包含一个 AsyncTask。在这个 AsyncTask 的 doInBackground()
中,你调用 newAdapter.updateList()
,在 updateList()
中,你调用 notifyDataSetChanged()
。
文档here says, that notifyDataSetChanged()
refreshs the UI. But as far as I know, refreshing the UI should only be possible from the UI thread, not from any background thread. You could try to call newAdapter.updateList()
in onPostExecute()
within the AsyncTask, see the example here。 doInBackground()
在后台线程上执行,onPostExecute()
在 UI 线程上执行。
public void retrievePosts(){
AsyncTask<Void,Void,Void> task = new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
Log.e("TAG",postList.get(0).text);
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute() {
newAdapter.updateList(postList);
}
};
runAsyncTask(task);
}
PS:我不认为捕获所有异常而不像 e.printStackTrace()
等
我有一个 android 应用程序,它的选项卡式布局包含一个列表视图。从服务器检索信息后,我正在尝试更新列表。但是,在触摸屏幕之前,列表不会更新。所有信息都是正确的,但无论我等多久,列表都不会显示在屏幕上,直到我点击它。有谁知道如何解决这个问题?
Tab1.java
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by hp1 on 21-01-2015.
*/
//NEW
public class Tab1 extends Fragment {
MainActivity mainActivity;
List<Post> postList;
public static NewAdapter newAdapter;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.tab_1,container,false);
return v;
}
@Override
public void onStart() {
super.onStart();
postList = new ArrayList<Post>();
try {
//get data from azure
mainActivity = (MainActivity) getActivity();
//set lists
ListView newListView = (ListView) mainActivity.findViewById(R.id.newListView);
newAdapter = new NewAdapter(mainActivity, postList);
newListView.setAdapter(newAdapter);
}catch(Exception e){
}
//get the posts loaded asynchronously
retrievePosts();
}
public void retrievePosts(){
AsyncTask<Void,Void,Void> task = new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
Log.e("TAG",postList.get(0).text);
newAdapter.updateList(postList);
} catch (final Exception e) {
}
return null;
}
};
runAsyncTask(task);
}
private AsyncTask<Void, Void, Void> runAsyncTask(AsyncTask<Void, Void, Void> task) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
return task.execute();
}
}
}
NewAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class NewAdapter extends BaseAdapter {
List<Post> postList;
Context context;
LayoutInflater inflater;
public NewAdapter(MainActivity mainActivity, List<Post> myPostList) {
postList=myPostList;
context=mainActivity;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return postList.size();
}
@Override
public Object getItem(int position) {
return postList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
PostCell postCell=new PostCell();
View cellView = inflater.inflate(R.layout.post_cell, null);
postCell.textView=(TextView) cellView.findViewById(R.id.textView1);
postCell.textView.setText(postList.get(position).text);
cellView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context, "You Clicked "+postList.get(position).text, Toast.LENGTH_LONG).show();
}
});
return cellView;
}
public List<Post> updateList(List<Post> myPostList){
postList = myPostList;
notifyDataSetChanged();
return postList;
}
public List<Post> addToList(Post post){
postList.add(post);
notifyDataSetChanged();
return postList;
}
}
编辑:最终答案 - 这是我解决问题的最终代码。 Bnydev 对这个问题的看法是正确的,但我还需要更改一些其他内容。
public void retrievePosts(){
//NOTE: must have a return type for an async task to run onpostexecute, which
//is executed on the ui thread so the screen can be updated
AsyncTask<Void,Void,Boolean> task = new AsyncTask<Void,Void,Boolean>(){
@Override
protected Boolean doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
} catch (final Exception e) {
e.printStackTrace();
}
return true;
}
protected void onPostExecute(Boolean reult) {
newAdapter.updateList(postList);
}
};
task.execute();
}
在 Tab1.java 中,您有方法 retrievePosts()
,其中包含一个 AsyncTask。在这个 AsyncTask 的 doInBackground()
中,你调用 newAdapter.updateList()
,在 updateList()
中,你调用 notifyDataSetChanged()
。
文档here says, that notifyDataSetChanged()
refreshs the UI. But as far as I know, refreshing the UI should only be possible from the UI thread, not from any background thread. You could try to call newAdapter.updateList()
in onPostExecute()
within the AsyncTask, see the example here。 doInBackground()
在后台线程上执行,onPostExecute()
在 UI 线程上执行。
public void retrievePosts(){
AsyncTask<Void,Void,Void> task = new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
try {
postList= mainActivity.postTable.execute().get();
Log.e("TAG",postList.get(0).text);
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute() {
newAdapter.updateList(postList);
}
};
runAsyncTask(task);
}
PS:我不认为捕获所有异常而不像 e.printStackTrace()
等