i am making a image downloading android app that takes a certain number of image urls, creates GUI for required for the number of urls provided and then displays them. I succeeded in doing so. Now i am trying to separate a module of this task. In order to do so i want to do everything out of the MainActivity class. The MainActivity class just provides the input in the form of urls and then takes the result back and displays it.
JAVA Code:
MainActivity Class:
public class MainActivity extends AppCompatActivity {
ArrayList<String> urls = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addUrls();
}
public void downloadImages(View view){
Manager manager = new Manager(MainActivity.this,urls);
manager.downloadImages();
}
public void addUrls() {
urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTXEZRoYOhIJxL5foNz_NlatDlgYStzZgVIiKuo6vtRtz2wY-8b4Q");
urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSFL3WYbqNOX-dwjtT1LroBlY5W-3YuwSIuCMRaLpnjMXbVPEJy");
urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQiwgrJeAJN-7lcy92N51uP7XzccK_p-fTSJNCXPLPSVih8wqPf");
urls.add("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT19dYLCEZlMRqojedJB-05jTrflD74nasvkXs-SdVeyM2BEpCSFA");
urls.add("http://wallpaperswide.com/download/high_tech_earth-wallpaper-2880x1800.jpg");
urls.add("https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg");
urls.add("https://images.unsplash.com/photo-1418489098061-ce87b5dc3aee?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=2f033882f3c25404e3f904fbfe2351be&w=1000&q=80");
urls.add("https://techcrunch.com/wp-content/uploads/2018/03/gettyimages-705351545.jpg?w=730&crop=1");
}
}
Manager class(a class that acts as a manager or GUI making class):
class Manager {
private Context context;
private ArrayList<String> urls = new ArrayList<>();
LinearLayout linearLayoutScrollView;
ImageView imageView;
ProgressBar progressBar;
RelativeLayout relativeLayout;
ImageDownloader imageDownloader;
public Manager(Context context, ArrayList<String> urls) {
this.context = context;
this.urls = urls;
}
public void buildUI() {
System.out.println("Error # 1");
imageView = new ImageView(context);
imageView.setVisibility(View.GONE);
System.out.println("Error # 2");
progressBar = new ProgressBar(context);
progressBar.setIndeterminate(true);
progressBar.setVisibility(View.GONE);
System.out.println("Error # 3");
relativeLayout = new RelativeLayout(context);
relativeLayout.addView(imageView);
relativeLayout.addView(progressBar);
System.out.println("Error # 4");
linearLayoutScrollView = (LinearLayout) findViewById(R.id.linearLayoutScrollView);
linearLayoutScrollView.addView(relativeLayout);
System.out.println("Error # 5");
}
public void downloadImages() {
for (int i = 0; i < urls.size(); i++) {
buildUI();
imageDownloader = new ImageDownloader(imageView,progressBar,imageDownloader);
progressBar.setVisibility(View.VISIBLE);
imageDownloader.execute(urls.get(i));
}
}
}
ImageDownloader Class:
public class ImageDownloader extends AsyncTask<String, Void, Bitmap> {
ImageView imageView;
ProgressBar progressBar;
ImageDownloader imageDownloader;
public ImageDownloader(ImageView imageView, ProgressBar progressBar, ImageDownloader imageDownloader) {
this.imageView = imageView;
this.progressBar = progressBar;
this.imageDownloader = imageDownloader;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
imageView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected Bitmap doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
System.out.println("Content Type = " + connection.getContentType());
if (connection.getContentType().contains("image")) {
InputStream inputStream = connection.getInputStream();
return BitmapFactory.decodeStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
try {
imageView.setImageBitmap(bitmap);
progressBar.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
XML Code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="match_parent"
tools:context="com.example.syeddanish.downloadingimages.MainActivity">
<LinearLayout
android:id="#+id/buttonsLinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<Button
android:id="#+id/downloadImagesButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="downloadImages"
android:text="Download Images" />
<Button
android:id="#+id/resetButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="reset"
android:text="Reset" />
</LinearLayout>
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/buttonsLinearLayout">
<LinearLayout
android:id="#+id/linearLayoutScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</ScrollView>
</RelativeLayout>
The issue is that in the "Manager"class it gives error to "add qualifier to method" in findViewById() method.
linearLayoutScrollView = (LinearLayout) findViewById(R.id.linearLayoutScrollView);
And if i add a this qualifier it changes the above line like this
linearLayoutScrollView = (LinearLayout) linearLayoutScrollView.findViewById(R.id.linearLayoutScrollView);
and then gives the error
logcat:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.syeddanish.downloadingimages, PID: 29339
java.lang.IllegalStateException: Could not execute method for
android:onClick
at
android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
at android.view.View.performClick(View.java:6291)
at android.view.View$PerformClick.run(View.java:24931)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at
android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:6291)
at android.view.View$PerformClick.run(View.java:24931)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'android.view.View
android.widget.LinearLayout.findViewById(int)' on a null object
reference
at
com.example.syeddanish.downloadingimages.Manager.buildUI(Manager.java:45)
at
com.example.syeddanish.downloadingimages.Manager.downloadImages(Manager.java:54)
at
com.example.syeddanish.downloadingimages.MainActivity.downloadImages(MainActivity.java:24)
at java.lang.reflect.Method.invoke(Native Method)
at
android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
at android.view.View.performClick(View.java:6291)
at android.view.View$PerformClick.run(View.java:24931)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
please point out what i am doing wrong and what to change to remove this issue.
findViewById is a method of View according to the official documentation:
Finds the first descendant view with the given ID, the view itself if the ID matches getId(), or null if the ID is invalid (< 0) or there is no matching view in the hierarchy.
or a method of activity:
Finds a view that was identified by the android:id XML attribute that was processed in onCreate(Bundle)
It is simple, It find a view inside a parent view. In most case, findviewById() is called inside an Activity, a Fragment or a CustomView. There, we call:
this.findViewById(ID_OF_THE_CHILD)
So, if you want to retrieve R.id.linearLayoutScrollView you need a reference to the parent view. you can pass it from buildGUI like this:
public void buildUI(View parent) {
...
linearLayoutScrollView = (LinearLayout)parent.findViewById(R.id.linearLayoutScrollView);
}
So, in Activity for example, you will call
buildGUI(findViewById(R.layout.activity_main));
the problem solved by putting this in the MainActivity class
linearLayoutScrollView = (LinearLayout) findViewById(R.id.linearLayoutScrollView);
and then then passing this linearLayoutScrollView as an argument in the the constructor of the "Manager" class.
public Manager(Context context, ArrayList<String> urls,LinearLayout linearLayoutScrollView) {
this.context = context;
this.urls = urls;
this.linearLayoutScrollView = linearLayoutScrollView;
}
and then making this linearLayoutScrollView as a local member of the "Manager" class and use it as required.
Related
I'm new to Android and I'm trying to display a list of comments with a "load more" button. But somehow my button is not triggered. It seems the listener doesn't do anything...
Here is my code:
public class CommentActivity extends AppCompatActivity {
ListView listComments;
private String FullJson = "";
private static int current_page = 0;
private int offset = 0;
public int getOffset() {
return current_page * 10;
}
private ProgressDialog pDialog = null;
protected String qid = "", udida="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comment);
listComments = (ListView) findViewById(R.id.listComments);
//get list of comments on this question
Intent intent = getIntent();
qid = intent.getStringExtra(QuestionActivity.EXTRA_QID);
udida = intent.getStringExtra(QuestionActivity.EXTRA_MESSAGE);
FullJson = intent.getStringExtra(QuestionActivity.EXTRA_JSON);
new HttpAsyncTask().execute("http://heycrowd.com/requests/questionWithComments.json?questionId="+qid+"&offset="+getOffset());
// LoadMore button
Button btnLoadMore = (Button) findViewById(R.id.load_more);;
//Listening to Load More button click event
btnLoadMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Starting a new async task
new GetIdTask().execute();
}
});
}
public String getIdThread () {
try {
Context ctx = CommentActivity.this.getApplicationContext();
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(ctx);
final String id = adInfo.getId();
return id;
} catch (GooglePlayServicesRepairableException e) {
return "Error 1";
} catch (IOException e) {
return "Error 2";
// Unrecoverable error connecting to Google Play services (e.g.,
// the old version of the service doesn't support getting AdvertisingId).
} catch (GooglePlayServicesNotAvailableException e) {
return"Error 3";
// Google Play services is not available entirely.
}
}
private class GetIdTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
// Showing progress dialog before sending http request
pDialog = new ProgressDialog(CommentActivity.this);
pDialog.setMessage("Please wait..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... urls) {
return getIdThread();
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
new HttpAsyncTask().execute("http://heycrowd.com/requests/questionWithComments.json?questionId="+qid+"&offset="+getOffset());
// closing progress dialog
pDialog.dismiss();
}
}
private List<HashMap<String,String>> getListItems(JSONArray FullJson) {
// Each row in the list stores country name, currency and flag
List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();
for(int i=0; i< FullJson.length() ;i++){
HashMap<String, String> hm = new HashMap<String,String>();
try {
hm.put("text", FullJson.getJSONObject(i).getString("text"));
hm.put("date", FullJson.getJSONObject(i).getString("created_at"));
//get user (picture + name)
JSONObject userObj = FullJson.getJSONObject(i).getJSONObject("user");
hm.put("user_id", userObj.getString("user_id"));
hm.put("user_name", userObj.getString("name"));
hm.put("user_img",userObj.getString("image_url"));
}
catch (JSONException e) {
//some exception handler code.
}
aList.add(hm);
}
return aList;
}
private void populateListView(JSONArray FullJson) {
setContentView(R.layout.activity_comment);
List<HashMap<String,String>> aList = getListItems(FullJson);
ListView listCommentView = (ListView) findViewById(R.id.listComments);
int currentPosition = listCommentView.getFirstVisiblePosition();
CommentAdapter adapter =new CommentAdapter(this, aList );
// Setting the adapter to the listView
listCommentView.setAdapter(adapter);
// Setting new scroll position
listCommentView.setSelectionFromTop(currentPosition + 1, 0);
//get logged user's image (at the moment, default image)
ImageLoader imageLoader = new ImageLoader(this.getApplicationContext());
ImageView image=(ImageView)findViewById(R.id.me_img);
image.setImageResource(R.drawable.ic_launcher);
}
private class HttpAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
return Utils.GET(urls[0]);
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(final String result) {
try {
JSONObject json = new JSONObject(result);
JSONArray commentsArr = json.getJSONObject("question").getJSONArray("comments"); // get comments array
populateListView(commentsArr);
} catch (JSONException e) {
//some exception handler code.
}
}
}
}
So when I get for the first time on my page, i get the first 10 comments, but when I click on my "load more" button: nothing happens.
I've set a point break on getIdTask() witch is supposed to be called on the click event, and I never get there. I can't seem to find why my button is not reacting to anything.
Also, I thought maybe calling several times an AsyncTask may be the problem, but I tried on the "OnCreate" to get the first 10 lines without an Asynctask, and then nothing worked anymore...
I'm stuck on this since yesterday, pls help!
I'm adding also the layout XML just in case:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="20dp"
android:orientation="vertical"
>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Load more comments"
android:id="#+id/load_more"
android:layout_marginBottom="10dp"
/>
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listComments"
android:focusable="false"
android:layout_weight="1.0"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:id="#+id/me_img"
android:layout_width="100dp"
android:layout_height="100dp"
android:contentDescription="user"
android:padding="5dp"
/>
<EditText
android:id="#+id/addComment"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="20dp"
android:minLines="3"
android:lines="5"
android:gravity="left|top"
android:scrollbars="vertical"
android:inputType="textMultiLine" >
<requestFocus />
</EditText>
</LinearLayout>
Thank you
I finally understood why my onclick listener was not working/triggered at all, it took me some time :-(
I have this code inside my populateListView method (first line)
setContentView(R.layout.activity_comment);
I removed it and it made all by listeners work again...
Probably this confused something here, to be honest i don't really understand :-(
I added a new Progress bar lib to my project. I added it through the maven. Then i used the progress bar in my layout file. While running the App it shows this Error.
Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.github.castorflex.android.circularprogressbar.CircularProgressBar
This is the Library i am using https://github.com/castorflex/SmoothProgressBar.
My layout File
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame">
<ListView
android:id="#+id/feed_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.github.castorflex.android.circularprogressbar.CircularProgressBar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:id="#+id/progressBar"
app:cpb_color="#FFee44"
app:cpb_colors="#array/colors"
app:cpb_rotation_speed="1.0"
app:cpb_sweep_speed="1.0"
app:cpb_stroke_width="4dp"
app:cpb_min_sweep_angle="10"
app:cpb_max_sweep_angle="300"
/>
</FrameLayout>
My Class
public class VideoActivity extends Activity {
private static final String TAG = "Mine";
private static final int REQ_START_STANDALONE_PLAYER = 1;
private static final int REQ_RESOLVE_SERVICE_MISSING = 2;
public static final String DEVELOPER_KEY = "AIzaSyDcnoqJGI1872s";
public ListView listView;
private FeedListAdapter listAdapter;
private List<FeedItem> feedItems;
public String mvideoid;
public String mstatus;
ProgressBar progressBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed_list);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
listView = (ListView) findViewById(R.id.feed_list);
feedItems = new ArrayList<FeedItem>();
listAdapter = new FeedListAdapter(this, feedItems);
listView.setAdapter(listAdapter);
// making fresh volley request and getting json
GsonRequest<FeedResult> gsonRequest = new GsonRequest<FeedResult>(URL_FEED, FeedResult.class,
new Response.Listener<FeedResult>() {
#Override
public void onResponse(FeedResult response) {
feedItems = response.getFeedItems();
listAdapter.setData(feedItems);
listAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.INVISIBLE);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Error: " + error.getMessage());
}
});
// Adding request to volley request queue
AppController.getInstance().addRequest(gsonRequest, TAG);
getid();
}
}
Try to replace with this :
xmlns:app="http://schemas.android.com/apk/res/com.android.demo"
this value (com.android.demo) replace with your package name.
if you are using any custom component refer it with the same name i.e.
import com.github.castorflex.android.circularprogressbar.CircularProgressBar;
public class VideoActivity extends Activity {
CircularProgressBar progressBar;
.
.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed_list);
progressBar = (CircularProgressBar) findViewById(R.id.progressBar);
.
.
.
you are using the default one which isn't present in xml
I've been having problems with this for quite some time now. I'm getting there little by little but I don't have much time to spend programming :(
So I'm having to load image from URLs for showing on a list view, and i'm almost there. They are lazy loading and the cache system i'm using works good.
The problem is that the downloaded images are in the wrong place when I start scrolling and I can't figure out where i'm going wrong.
The code is inspired from these two links:
This one for the layout idea.
http://blog.blundell-apps.com/imageview-with-loading-spinner/
and this one for the cache system.
http://android-developers.blogspot.fr/2010/07/multithreading-for-performance.html
So here's my code:
public class LoaderImageView extends LinearLayout
{
private static final String TAG = "LoderImageView";
private Context mContext;
private ImageView mImage;
private ProgressBar mSpinner;
/* The HashMap that contains the references to the different
* downloads currently running.
*/
public static HashMap<LoaderImageView, BitmapDownloaderTask> tasks =
new LinkedHashMap<LoaderImageView, BitmapDownloaderTask>();
public LoaderImageView(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
mImage = new ImageView(mContext);
mImage.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mSpinner = new ProgressBar(mContext);
mSpinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
mSpinner.setIndeterminate(true);
addView(mSpinner);
addView(mImage);
Log.w(TAG, "Loading an imageView");
}
public void downloadImage(String url)
{
resetPurgeTimer();
//Log.w(TAG, "Loading: " + url);
if(url.equals(""))
{
mImage.setImageDrawable(mContext.getResources().getDrawable(R.drawable.male));
}
else
{
Bitmap bitmap = getBitmapFromCache(url);
if(bitmap == null)
{
/* The bitmap is not in the cache. */
cancelPotentialDownload(this);
/* Start the new download. */
BitmapDownloaderTask bdt = new BitmapDownloaderTask(this, url);
bdt.execute();
}
else
{
/*The bitmap is in the cache. */
mImage.setImageBitmap(bitmap);
mSpinner.setVisibility(View.GONE);
}
}
}
class BitmapDownloaderTask extends AsyncTask<Void, Void, Bitmap>
{
private String mUrl;
private LoaderImageView mLiv;
public BitmapDownloaderTask(LoaderImageView liv, String url)
{
mLiv = liv;
mUrl = url;
}
#Override
protected void onPreExecute()
{
LoaderImageView.tasks.put(mLiv, this);
mSpinner.setVisibility(View.VISIBLE);
mImage.setVisibility(View.GONE);
Log.w(TAG, "Starting an AsyncTask");
}
#Override
protected Bitmap doInBackground(Void... voids)
{
URL url = null;
try
{
url = new URL(mUrl);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
return BitmapTools.fetchBitmap(url);
}
#Override
protected void onPostExecute(Bitmap bitmap)
{
BitmapDownloaderTask b = tasks.get(mLiv);
if(b == this)
{
LoaderImageView.tasks.remove(this);
mImage.setImageBitmap(bitmap);
}
if (isCancelled())
{
bitmap = null;
}
addBitmapToCache(mUrl, bitmap);
tasks.remove(mLiv);
mSpinner.setVisibility(View.GONE);
mImage.setVisibility(View.VISIBLE);
}
}
/* More methods related too the cache... */
Here the xml layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/list_item_selector" >
<com.myproject.liste.LoaderImageView
android:id="#+id/visites_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
</RelativeLayout>
I'm creating the list with a BaseAdapter and ListActivity.
Also i'm loading the list by pages of data: I load 10 items, when the user scrolls down I load 10 more, and call notifyDataSetChange();
I have an asynctask of which's onPostExecute i am calling a function to show a customDialog.
This is my AsyncTask
private class DBTask extends AsyncTask<Long, Boolean, Integer>{
ProgressDialog ServerPD = new ProgressDialog(MRRankingActivity.this);
#Override
protected void onPreExecute()
{
ServerPD = ProgressDialog.show (MRRankingActivity.this, "", "Connecting to server...", true, false);
}//End of onPreExecute
#Override
protected Integer doInBackground(Long... params)
{
int isSuccess=0;
publishProgress(isOnline());
if(isOnline())
{
getDBData();
if(isOK)
{
isSuccess=1;
}
}
}
return isSuccess;
}
#Override
protected void onProgressUpdate(Boolean... isConnection) {
// TODO Auto-generated method stub
super.onProgressUpdate(isConnection);
if(isOnline())
{
ServerPD.setMessage("Retreving Data");
}
}
#Override
protected void onPostExecute(Integer result) {
if (ServerPD.isShowing())
{
ServerPD.dismiss();
}
if(result==1)
{
customDialog();
}
}//End of onPostExecute
}//End of DBTask
And this is my customDialog function
public void customDialog(){
Dialog dialog=new Dialog(MRRankingActivity.this);
dialog.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
dialog.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.string.app_name );
dialog.setContentView(R.layout.result_dialog);
final ListView ResultView = (ListView) findViewById( R.id.ListResult );
result_Adapter=new ArrayAdapter<String>(MRRankingActivity.this,android.R.layout.simple_list_item_1,result_Array);
//Bind Array Adapter to ListView
ResultView.setAdapter(result_Adapter);
dialog.show();
}//end of custom dialog function
This is my result_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical">
<ListView android:id="#+id/ListResult"
android:layout_height="wrap_content"
android:layout_width="fill_parent"/>
</LinearLayout>
</RelativeLayout>
Now when i run this code i am getting this error
FATAL EXCEPTION: main
java.lang.NullPointerException
at com.lalsoft.mobileranking.MRRankingActivity.customDialog(MRRankingActivity.java)
at com.lalsoft.mobileranking.MRRankingActivity$DBTask.onPostExecute(MRRankingActivity.java) at com.lalsoft.mobileranking.MRRankingActivity$DBTask.onPostExecute(MRRankingActivity.java)
at android.os.AsyncTask.finish(AsyncTask.java)
at android.os.AsyncTask.access$300(AsyncTask.java)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java)
at android.os.Handler.dispatchMessage(Handler.java)
at android.os.Looper.loop(Looper.java)
at android.app.ActivityThread.main(ActivityThread.java)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java)
If i comment
//ResultView.setAdapter(result_Adapter);
in my customDialog function,the customDialog will show,without the Listview. This error is coming when i set the adapter to my ListView.
How to solve this issue??What should be done?? Please help
Replace this line final ListView ResultView = (ListView)dialog.findViewById( R.id.ListResult );
instead of final ListView ResultView = (ListView)findViewById( R.id.ListResult );
In your code your result_Adapter may be null. Thats why when you set it to ResultView its showing NullPointerException.
Also check if result_Array contain values or not.
The list view is not updating data when the notifyDataChanged() method called.
In onCreate() method i initialized the the listview with no data.
ListView videoList = (ListView)findViewById(R.id.videos_list);
videoList.setOnItemClickListener(listener);
listAdapter = new PHVideosListAdapter(PHVideosActivity.this, videos);
videoList.setAdapter(listAdapter);
After this I started fetching list of video using new VideosCategoryFetchTask().execute();
in the post execute method I called
#Override
protected void onPostExecute(Boolean success) {
if(success) {
listAdapter.notifyDataSetChanged();
} else {
//show dialog
}
}
but nothing is displayed on the list. If anybody knew the solution please help...
private class VideosDetailsFetchTask extends AsyncTask<String, Void, Boolean> {
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... params) {
Boolean success = false;
try {
if (params.length >= 0) {
videos = (Videos)videoAPI.videosForCategoryId(params[0],new VideosParser());
success = true;
}
} catch (Exception e) {
// TODO: handle exception
}
return success;
}
#Override
protected void onPostExecute(Boolean success) {
if(success) {
progressBar.setVisibility(View.INVISIBLE);
onFinishVideoFetch();
} else {
//show dialog
}
}
}
here using two Async classes sec one is called on the onPostExecute() of first one..
private void onFinishVideoFetch() {
if(videos != null) {
listAdapter.notifyDataSetChanged();
}
}
I 'm not fetching videos one by one.. here a list of videos is returned....
After getting the list of videos i wanted to refresh the list.
#Override
protected void onProgressUpdate(Videos... values) {
videos = values[0];
//add published object to list which holds
listAdapter.notifyDataSetChanged();
}
I tried this but no luck please help..
this is the adapter class used
public class PHVideosListAdapter extends BaseAdapter{
private Videos videoTitles;
private LayoutInflater inflater;
public PHVideosListAdapter(Context context, Videos videoTitles) {
inflater = LayoutInflater.from(context);
this.videoTitles = videoTitles;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
if(videoTitles != null) {
return videoTitles.size();
}
else {
return 0;
}
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return videoTitles.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
VideoListViewHolder holder = null;
if (convertView == null) {
holder = new VideoListViewHolder();
convertView = inflater.inflate(R.layout.videos_list, null);
holder.videoTitle = (TextView) convertView.findViewById(R.id.video_title);
holder.videoImage = (ImageView) convertView.findViewById(R.id.video_image);
holder.videoDuration = (TextView) convertView.findViewById(R.id.video_duration);
convertView.setTag(holder);
} else {
holder = (VideoListViewHolder)convertView.getTag();
}
holder.videoImage.setImageResource(R.drawable.icon);
holder.videoDuration.setText("00:10");
holder.videoTitle.setText(videoTitles.get(position).getVideoTitle());
return convertView;
}
private class VideoListViewHolder {
ImageView videoImage;
TextView videoTitle;
TextView videoDuration;
}
}
When you first create your PHVideosListAdapter, it is holding a reference to the Videos list that I assume is a member of your Activity. In your doInBackground method, the call to videoAPI.videosForCategoryId is updating the Videos reference in your Activity, but the adapter is still holding the original reference that was passed in to the constructor for PHVideosListAdapter. You need to either recreate the PHVideosListAdapter in onPostExecute or add a set method in PHVideosListAdapter to change the private variable videoTitles.
I ran into the same issue with using the ArrayAdapter provided by Google. You can only set the underlying List in the constructor, so you must recreate the ArrayAdapter or create your own class that allows changing of the underlying data for notifyDataSetChanged to work.
You need to override onProgressUpdate() of AsynTask class
Heres an example of AsyncTask assuming your list is videos which holds Objects of type Video and your extended adapter is VideosAdapter
private class VideosDetailsFetchTask extends AsyncTask<String, Video, Boolean> {
#Override
public void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(String... params) {
//utilize string you are passing otherwise use Void as first generic param.
Boolean success = false;
try {
if (params.length >= 0) {
Videos videoFetched = (Videos)PrimeraHoraAPI.videosForCategoryId(params[0],new VideosParser());
success = true;
publishProgress(videoFetched);
}
} catch (Exception e) {
// TODO: handle exception
}
return success;
}
#Override
protected void onPostExecute(Boolean success) {
if(success) {
progressBar.setVisibility(View.INVISIBLE);
onFinishVideoFetch();
} else {
//show dialog
}
}
#Override
protected void onProgressUpdate(Video... values) {
videos.add(values[0]);//add published object to list which holds
((VideosAdapter)getListAdapter()).notifyDataSetChanged();
}
}
It's not very good descript anywhere but what you do when u call
listAdapter.notifyDataSetChanged();
u tell your machine "oke, your code is not legit" and now u stop! so basically ur machine has no clue what 2 do next! My solution is:
create a private void setupData()
private void setupData() {
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
final List<Table_Follow> data = db.getAllData(); // from database
HashMap<String,String> item;
for(Table_Data td : data){
item = new HashMap<String,String>();
item.put("name1", td.getName_One());
item.put("name2", td.getName_Two());
item.put("date", td.getDate());
list.add(item);
};
my_data = new SimpleAdapter(this, list, R.layout.my_listview_row, new String[] { "name1","name2", "date" }, new int[] {R.id.lv_line_a, R.id.lv_line_b, R.id.lv_line_c});
listview.setAdapter(my_data);
}
I have a custom layout with 3 textviews (line a > title, line b > subtitle, line c > time see bottom page for xml). So basicly i ll use this private void to tell my machine what 2 do next by using setupData() after calling > notifydatasetchanged() in my main thread
my_data.notifyDataSetChanged();
setupData();
One last thing! I use the android listview id for my listview in my main xml file! Oh and if you have trouble using your 'onItemClickListener' (not giving u the right id, just text me! I faced that problem and solved it pretty shitty but it works :p)
My xml file for my listview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<TextView
android:id="#+id/lv_line_c"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="15sp" />
<LinearLayout
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/lv_line_a"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:id="#+id/lv_line_b"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="15sp" />
</LinearLayout>
</RelativeLayout>