I have this arraylist:
List<View> mListViews = new ArrayList<View>();
which is populated by
addView(mListViews, "file:///android_asset/a.html");
addView(mListViews, "file:///android_asset/b.html");
addView(mListViews, "file:///android_asset/c.html");
and the addView method:
private void addView(List<View> viewList,String url) {
WebView webView=new WebView(this);
webView.loadUrl(url);
viewList.add(webView);
}
I would like to get the element from the second position in the arraylist as a string. So the expected result is file:///android_asset/b.html. I tried
String test = mListViews.get(1);
But I received error incompatible type, required java.lang.String, found android.view.View.
How to solve this?
If this was my issue, I would do the following:
Create a model class...
public class ListModel {
View view;
String url;
public ListModel (View view, String url) {
this.view = view;
this.url = url;
}
public View getView() {
return view;
}
public void setView(View view) {
this.view = view;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Make a list that takes in that class...
public class MainActivity extends AppCompatActivity {
List<ListModel> listModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listModel = new ArrayList<>();
listModel.add(new ListModel(view, "url"));
}
}
From there you can create a for loop to get the view and / or the url..
for (int i = 0; i < listModel.size(); i++) {
View getView = listModel.get(i).getView();
String getUrl = listModel.get(i).getUrl();
}
Now, keep in mind, my code will NOT work because I didn't create a VIEW to put into the list. But this is probably the best way to go about it.
Use this:
String test = ( (WebView) mListViews.get(1) ).getUrl();
Be aware that if you do this before a page has finished loading, test will be null.
Another option would be to create a class encapsulating a WebView and the url string, then creating a list of objects of that class.
As you write you have ArrayList of View type.
Result of mListViews.get(1) is type of View. You can't assign View to String variable.
Question is for what you creating ArrayList<View> and populate it with WebView?
If you need the url from the webView I think you just need to do this:
String test = mListViews.get(1).getURL();
Related
My app doesn't display anything when passing data from one class to another. I located through with the debugger that my ArrayList doesn't get the right value from the class.
I'm sending data with the following function:
public class Adaugare extends AppCompatActivity {
private ListView myListView;
private NumeAdapter numeAdapter;
String inume;
int ivarsta;
Intent intent = new Intent();
private ArrayList persoanaArrayList = new ArrayList<>();
public ArrayList getPersoanaArrayList() {
return persoanaArrayList;
}
public int getPersoanaArrayListsize() {
return persoanaArrayList.size();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_adaugare);
myListView = (ListView) findViewById(R.id.persoana_list);
Button btn_fin = (Button) findViewById(R.id.btn_fin);
btn_fin.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText nume_edit_text = (EditText) findViewById(R.id.ins_nume);
EditText varsta_edit_text = (EditText) findViewById(R.id.ins_var);
ivarsta = Integer.parseInt(varsta_edit_text.getText().toString());
inume = nume_edit_text.getText().toString();
persoanaArrayList.add(new Persoana(inume, ivarsta));
}
});
}
}
And recieving it with:
public class Afisare extends AppCompatActivity {
ListView myListView;
NumeAdapter numeAdapter;
Adaugare ad = new Adaugare();
int cate;
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_afisare);
myListView = (ListView) findViewById(R.id.persoana_list);
ArrayList<Persoana> persoanaArrayList = new ArrayList<Persoana>(ad.getPersoanaArrayList());
numeAdapter = new NumeAdapter(this, persoanaArrayList);
myListView.setAdapter(numeAdapter);
}
The class Persoana is:
public class Persoana {
private String nume;
private int varsta;
Persoana(String inume, int ivar) {
this.nume = inume;
this.varsta = ivar;
}
public String getNume() {
return nume;
}
public int getVarsta() {
return varsta;
}
public void setNume(String nume) {
this.nume = nume;
}
public void setVarsta(int varsta) {
this.varsta = varsta;
}
}
Persoana is the main class, everything is saved in it. ad is an object of Adaugare, Adaugare being the class from which I've taken the code for getPersoanaArrayList. At debugging some values appeared at ad, namely Adaugare #4556, and persoanaArrayList remains null.
I need the persoanaArrayList so that i can initialize my Adapter and listView. Everything else in the code seems fine from step by step testing with debugger.
Your problem is with the following line in the Afisare class:
Adaugare ad = new Adaugare();
You can't simply new one activity from another activity and expect to access a shared list between them. To share instance data between java objects you need a reference to the other object. Creating a new instance will create a new empty list. That's why you are "losing" data. A quick fix would be to make the list static so it can be accessed from any instance.
But since you're dealing with Android, the right way to share data between activities is by using intent extras. The first activity starts the second activity via an intent. The first activity places the desired data in the intent as extras. The second activity uses getIntent() and the various methods on Intent to access the extras.
One last tip, in Android, you never use the new operator with Activities. Activities are created by the system to service an intent. If you find yourself using the new operator, that's a sign that you're doing something wrong.
I'm pretty new to developing in Android, but I understand that I cannot run Jsoup.connect(url).get() without some kind of thread as it is a synchronous call. I tried creating a class called Product that extends AsyncTask, and then having my original class called List call Product and then have the int displayed. However, regardless of the actual result, it always prints out 0.
I have tested my code before, so I know it works and that the issue must be something related to Android.
List Class:
public class List extends AppCompatActivity{
String itemURL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Bundle itemData = getIntent().getExtras();
if(itemData==null){
return;
}
//Gets URL
itemURL = itemData.getString("itemURL");
int listSize=new Product(itemURL).getListSize();
System.out.println(listSize);
}
}
Product class:
public class Product extends AsyncTask<Void,Void,Void>{
String url;
String title;
int listSize;
public Product(String url){
this.url = url;
}
protected Void doInBackground (Void... voids) {
//Create JSoup connection
try{
Document doc = Jsoup.connect("url").get();
//Gets title
String link = doc.select("h2#s-result-count").first().text();
System.out.println(link);
listSize=Integer.parseInt(link.substring(0,1));
System.out.println(listSize);
try{
int listSize= Integer.parseInt(link.substring(0,2));
System.out.println(listSize);
}catch(Exception e){}
}catch (Exception e){}
}
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
getListSize();
}
public int getListSize(){
return listSize;
}
}
All advice would be appreciated, thanks for your time and help!
You have to override
onPostExecute()
to make sure you are getting the variable after it is updated from the thread. Call your
getListSize()
from inside the overridden function.
Consider that calling
execute()
and then immediately calling
getListSize()
will happen line by line while the actual thread you have spun off will continue working. You're asking for a value that hasn't been updated.
Edit::
For clarification:
public class List extends AppCompatActivity{
String itemURL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Bundle itemData = getIntent().getExtras();
if(itemData==null){
return;
}
//Gets URL
itemURL = itemData.getString("itemURL");
int listSize=new Product(itemURL).getListSize(); // this doesn't do anything meaningful for you
System.out.println(listSize);
}
}
Note the comment I have added to
int listSize = new Product(itemURL).getListSize();
First,
doInBackground()
will never run until you call
execute()
You need to call
new Product(itemURL).execute();
Afterword, you have to provide some kind of callback to the Activity since you haven't nested the product class or initialized an anonymous instance of AsyncTask.
In your Product class you can set a variable
Context
public class Product extends AsyncTask<...> {
public Context context;
}
Then, in place of
int listSize = new Product(itemURL).getListSize();
put:
Product product = new Product();
product.context = this;
product.execute();
Then, in Product's
onPostExecute()
put:
if (context.getClass().equals(List.class)) {
((List) context).some_method_that_does_something_with_list_size()
}
Alternatively, you can add it to Product's constructor:
public Product(String url, Context context) {...}
Edit 2::
For further clarification
((List) context).some_method_that_does_something_with_list_size()
was meant to serve as a placemarker for any method available in your activity. It could easily be substituted with:
System.out.println(listSize);
Edit 3::
For further, further clarification:
In your Activity, ItemListView, define a method called
printListSize(int listSize) {
System.out.println("list size: " + listSize);
}
Then, in onPostExecute() call:
((ItemListView) context).printListSize(listSize);
How can i send data from an activity to a class ?
I tried to pass a String using getter but this gives me the initial value of the variable , but my String's value changes in my onCreate. Any ideas how can i pass it to my class ?
Here is some code :
public class MainActivity extends AppCompatActivity {
private String global ;
public String getGlobal() {
return global;
}
...
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
global = String.valueOf(parent.getItemAtPosition(position));
}
});
}
And here is my class
public class SimpleVar {
MainActivity mainActivity = new MainActivity() ;
String data = mainActivity.getGlobal; }
Any help will be much appreciated. Thank you in advance !
global is not actually "global"
Each instance of the Activity has its own string, and the OS can decide to kill your Activity at any time and recreate it, so therefore don't rely on a variable from an Activity within another class.
Secondly, never ever make a new Activity. That is no longer tied to the Activity that you would eventually click the button on.
It's hard to determine what you really need, but this is more correct.
public class SimpleVar {
String data;
}
With the Activity sending data to it
private SimpleVar var;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
var = new SimpleVar();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
var.data = String.valueOf(parent.getItemAtPosition(position));
}
});
}
If you need that object elsewhere, you need to pass it around to those classes from this Activity
try to make constructor for your class
public class SimpleVar {
private String data;
public SimpleVar(String data) {
this.data = data;
}
public void setData(String data) {
this.data = data;
}
}
then in your activity new the class and then set data to it
You should not create new mainactivity in your class.
When on instantiating the class pass to it a reference to Activity in which the class was created. Reference to Activity should be kept in a weakreference. Then You can make a getter in the Activity and call it from Your class.
Or You can do the opposite - keep reference to the instantiated object in the Activity. Use setter from the activity to pass new values to the object.
I've been looking for a similar problem to mine in order to find a solution, but I seriously couldn't find anything like that.
I was trying to download from parse an array of posts with an asynctask class, and after it gets the posts, it suppose to set the posts array in my page, and perform the setAdapter function in order to set my new posts array.
the problem is, after I've initialized listView and listAdapter in my home fragment,and then I perform the postArray taking from parse function, after it finishes taking the posts array from parse, it cannot update listAdapter because it says the listAdapter and my listView "haven't initialized yet", even though they have.
p.s.
sorry for not posting my code in a convenient way, I don't tend to post my code problems that often.
here's my code:
my home fragment:
public class HomeFragment extends Fragment {
View root;
ArrayList<PostClass> postsArrayList = new ArrayList<>();
static boolean isPostsArrayUpdated = false;
ListAdapter listAdapter;
PullToRefreshListView listView;
public void updatePostsArrayList(ArrayList<PostClass> postsArrayList){
if(!isPostsArrayUpdated){
// First time updating posts array list
listAdapter = new ListAdapter(getActivity(), root);
listView = (PullToRefreshListView) root.findViewById(R.id.list_container);
this.postsArrayList = postsArrayList;
listView.setAdapter(listAdapter);
isPostsArrayUpdated = true;
root.findViewById(R.id.homeFragmentLoadingPanel).setVisibility(View.GONE);
}else{
// Have updated posts before
this.postsArrayList = postsArrayList;
listAdapter.notifyDataSetChanged();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.fragment_home, container, false);
listView = (PullToRefreshListView) root.findViewById(R.id.list_container);
listAdapter = new ListAdapter(getActivity(), root);
Home_Model.getInstance().setPostsArrayList();
return root;
}
public class ListAdapter extends BaseAdapter implements View.OnClickListener{//....}
my home model:
public class Home_Model {
Home_Model(){}
static final Home_Model instance = new Home_Model();
public static Home_Model getInstance() {
return instance;
}
public void setPostsArrayList(){
new setHomePostsArray().execute();
}
public class setHomePostsArray extends AsyncTask<Void, ArrayList<PostClass>, Void>{
ArrayList<String> followersList;
ArrayList<PostClass> postsArrayList;
#Override
protected Void doInBackground(Void... params) {
// Getting posts from parse
String userName = Parse_model.getInstance().getUserClass().get_userName();
followersList = Parse_model.getInstance().getFollowersByUserNameToString(userName);
followersList.add(userName);
postsArrayList = Parse_model.getInstance().getAllUsersPostsByFollowings(followersList);
for (PostClass currPost : postsArrayList) {
for (PostClass currLocalDBPost : LocalDBPostsArray) {
if (currPost.getObjectID().equals(currLocalDBPost.getObjectID())) {
currPost.set_postPicture(currLocalDBPost.get_postPicture());
}
}
}
//Updating home page
onProgressUpdate(postsArrayList);
// Updating local data base in new posts
//checking in local DB if there are any new posts from parse and update them
for (PostClass currPost : postsArrayList) {
boolean isPostExists = false;
for (PostClass currLocalPost : LocalDBPostsArray) {
if (currPost.getObjectID().equals(currLocalPost.getObjectID())) {
isPostExists = true;
}
}
if (!isPostExists) {
ModelSql.getInstance().addPost(currPost);
Log.e("post not exist", "adding local DB");
}
}
//updating followers list in local DB
Parse_model.getInstance().getUserClass().setFollowersArray(followersList);
ModelSql.getInstance().updateFollowersArray(currUser);
return null;
}
#Override
protected void onProgressUpdate(ArrayList<PostClass>... values) {
//pass the updated postsArrayList to home fragment
if(setPostsInHomePageDelegate!= null){
setPostsInHomePageDelegate.setPosts(values[0]);
}
}
}
public interface SetPostsInHomePage {
public void setPosts(ArrayList<PostClass> postsArrayList);
}
SetPostsInHomePage setPostsInHomePageDelegate;
public void setSetPostsInHomePageDelegate(SetPostsInHomePage setPostsInHomePageDelegate) {
this.setPostsInHomePageDelegate = setPostsInHomePageDelegate;
}
main activity:
public class MainActivity extends Activity {
static HomeFragment homeFragment = new HomeFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// the home fragment has already been opened during the app opening
//...
setPostsImHomePage();
}
//...
public void setPostsImHomePage(){
Home_Model.getInstance().setSetPostsInHomePageDelegate(new Home_Model.SetPostsInHomePage() {
#Override
public void setPosts(ArrayList<PostClass> postsArrayList) {
homeFragment.updatePostsArrayList(postsArrayList);
}
});
}
}
Try to move your method setPostsImHomePage(...) from MainActivity to HomeFragmentand call it in OnCreateView before return root;.
Try initializing homeFragment in onCreate before your method call. It's also helpful to know which line(s) are giving you errors.
Obviously your fragment has no View when the result arrives.
You should properly add the fragment to the Activity using the FragmentManager, then in the Fragment's onActivityCreated() callback (which is called by the system after the Fragment has its view properly set), start your AsyncTask.
I'm a newcomer on Android and in the Google Guide I'm in this part: http://developer.android.com/training/basics/data-storage/databases.html.
Yes, it's about the dabatase, but to put it in practice, in my dummy studying app I created a simple system for store "profiles" to have something to store in the database. Basically, I've created an Activity for fill some text fields and store it in the database. And a class called ProfileDao that do the CRUD stuff.
I've reached a point where I want to build an activity to show all profiles added, using a LinearLayout. The problems is that I can't stack the views in code as the XML does.
Here is some code:
The ProfileFragment class:
public final class ProfileFragment extends Fragment {
private String _name;
private String _gender;
private int _age;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View retVal = inflater.inflate(R.layout.profile_fragment, container, false);
final TextView _nameField = (TextView) retVal.findViewById(R.id.profile_fragment_name);
final TextView _genderField = (TextView) retVal.findViewById(R.id.profile_fragment_gender);
final TextView _ageField = (TextView) retVal.findViewById(R.id.profile_fragment_age);
_nameField.setText(_name);
_genderField.setText(_gender);
_ageField.setText(String.valueOf(_age));
return retVal;
}
public void setName(String name) { _name = name; }
public void setGender(String gender) { _gender = gender;}
public void setAge(int age) { _age = age; }
public String getName() { return _name; }
public String getGender() { return _gender; }
public int getAge() { return _age; }
}
My intent initially was to use this fragment to dinamically put it in a LinearLayout, but I quickly saw I can't do this and made this class just a util for return a view.
The SeeProfilesActivity:
public class SeeProfilesActivity extends Activity {
private static final String TAG = makeLogTag(SeeProfilesActivity.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.see_profiles_activity);
final ProfileDao profDao = new ProfileDao(new ProfileDbHelper(this));
final List<Profile> profiles = profDao.getProfiles();
LOGD(TAG, "PROFILES RETRIEVED");
if(profiles.size() == 0) {
final TextView thereisNotProfiles = new TextView(this);
thereisNotProfiles.setText(getString(R.string.there_is_not_profiles));
thereisNotProfiles.setTextSize(35);
LOGD(TAG, "NO PROFILES, SO JUST DISPLAY THERE IS NOT");
setContentView(thereisNotProfiles);
return;
}
addFragmentProfiles(profiles);
}
private void addFragmentProfiles(List<Profile> profiles) {
final LinearLayout itLayout = (LinearLayout) ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0);
itLayout.setOrientation(LinearLayout.VERTICAL);
View currView;
for(Profile prof : profiles) {
final ProfileFragment profFrag = new ProfileFragment();
profFrag.setName(prof.getName());
profFrag.setGender(prof.getGender());
profFrag.setAge(prof.getAge());
LOGD(TAG, "WELL, ONE PROFILE WAS RETRIEVED");
currView = profFrag.onCreateView(getLayoutInflater(), itLayout, null);
itLayout.addView(currView);//here is my problem
LOGD(TAG, "SUCCESS IN DISPLAY");
}
}
}
How do I reproduce the behaving of stacking the views present in a LinearLayout XML in code?
Before some objections:
I know some of you will say there's a better way to do it, mainly the experient developers (maybe saying I can use ListView with adapters. Yes, I know it, but I didn't reach this part of the guide yet). But, get the fact I'm a very fresh beginner and really want to do this by hand to enjoy the maximum of what a learn.
Change the fragment layout "profile_fragment" height is wrap_content,not fill or match parent.
My english is not well,I hope you can understand ....
R.Layout.profile_fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" // This is your problem.
android:orientation="vertical" >