How to correctly handle data management with SharedPreferences? - json

Right now, I am in the process of "optimizing" my app. I am still a beginner, so what I am doing is basically moving methods from my MainActivity.class to their separate class. I believe it's called Encapsulation (Please correct me if I'm wrong).
My application needs to :
Get a YouTube Playlist Link from the YouTube App (with an Intent, android.intent.action.SEND).
Use the link to fetch data from the Google Servers with the YouTubeApi and Volley.
Read the data received and add it to an arrayList<String>.
What my YouTubeUsage.java class is supposed to do, is fetch data with the YouTubeApi and Volley then store the data using SharedPreferences. Once the data is saved, the data is being read in my ConvertActivity.class (It's an activity specifically created for android.intent.action.SEND) with my method getVideoIds() before setting an adapter for my listView in my createRecyclerView() method.
YouTubeUsage.java
public class YoutubeUsage {
private Boolean results = false;
private String mResponse;
private ArrayList<String> videoIds = new ArrayList<>();
String Url;
public String getUrl(String signal) {
String playlistId = signal.substring(signal.indexOf("=") + 1);
this.Url = "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" +
playlistId + "&maxResults=25&key=" + "API_KEY";
return this.Url;
}
public void fetch(String Url, final Context context){
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest request = new StringRequest(Request.Method.GET, Url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
sharedPreferences(response, context);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VolleyError", Objects.requireNonNull(error.getMessage()));
}
});
queue.add(request);
}
private void sharedPreferences(String response, Context context){
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = m.edit();
if (m.contains("serverResponse")){
if (!m.getString("serverResponse", "").equals(response)){
editor.remove("serverResponse");
editor.apply();
updateSharedPreferences(response, context);
}
} else{
updateSharedPreferences(response, context);
}
}
private void updateSharedPreferences(String mResponse, Context mContext){
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = m.edit();
editor.putString("serverResponse", mResponse);
editor.apply();
}
}
ConvertActivity.java
public class ConvertActivity extends AppCompatActivity {
YoutubeUsage youtubeUsage = new YoutubeUsage();
ArrayList<String> videoIDs = new ArrayList<>();
String Url = "";
ListView listView;
MyCustomAdapter myCustomAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_convert);
listView = findViewById(R.id.listview_convert);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
}
//I would like to avoid the try/catch below
try {
videoIDs = getVideoIDs(Url, this);
createRecyclerView(videoIDs);
Log.i("ResponseVideoIDs", String.valueOf(videoIDs.size()));
} catch (JSONException e) {
e.printStackTrace();
}
}
private ArrayList<String> getVideoIDs(String Url, Context context) throws JSONException {
ArrayList<String> rawVideoIDs = new ArrayList<>();
youtubeUsage.fetch(Url, context);
SharedPreferences m = PreferenceManager.getDefaultSharedPreferences(context);
String serverResponse = m.getString("serverResponse", "");
JSONObject jsonObject = new JSONObject(serverResponse);
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i<jsonArray.length(); i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject jsonVideoId = jsonObject1.getJSONObject("contentDetails");
rawVideoIDs.add(jsonVideoId.getString("videoId"));
}
return rawVideoIDs;
}
private void createRecyclerView(ArrayList<String> videoIDs){
myCustomAdapter = new MyCustomAdapter(this, videoIDs);
listView.setAdapter(myCustomAdapter);
myCustomAdapter.notifyDataSetChanged();
}
}
Everything works fine, however, my sharedPreferences never gets updated. Which means, if I share a YouTube playlist from the YouTube App to my app with 3 items in it, it will work fine. The Listview will show 3 items with their corresponding IDs as it should. But, if I share a YouTube playlist again, my app will still hold on to the data of the previous playlist I shared (even if I close it), showing the item number and the IDs of the previous link. If i continue to share the same playlist over and over, it will eventually show the correct number of items and the correct IDs.
I could totally put all my methods from the YouTubeUsage.java in my ConvertActivity.class preventing me from using SharedPreferences to transfer data between the two java classes. However, JSON throws an exception. That means I have to encapsulate my code with try/catch. I would like to avoid those since I need to do a lot of operations on the data just received by Volley (check a class size, look for certains strings). I find that doing this in these try/catch don't work like I want. (i.e. outside the try/catch, the values remains the same even if I updated them in the try/catch).
I want to know two things.
How can I correct this problem?
Is this the most efficient way to do this (optimization)? (I though of maybe
converting the VolleyResponse to a string with Gson then store the String file, but I don't know if that's the best way to do it since it's supposed to be
provisional data. It feels like just more of the same).
Thank You!

There is an issue with making assumptions about order of events. Volley will handle requests asynchronously, so it is advisable to implement the observer pattern here.
Create a new Java file that just contains:
interface MyNetworkResponse {
void goodResponse(String responseString);
}
Then make sure ConvertActivity implements MyNetworkResponse and create method:
void goodResponse(String responseString) {
// handle a positive response here, i.e. extract the JSON and send to your RecyclerView.
}
within your Activity.
In your YoutubeUsage constructor, pass in the Activity context (YoutubeUsage) and then store this in a YoutubeUsage instance variable called ctx.
In onCreate, create an instance of YoutubeUsage and pass in this.
In onResponse just call ctx.goodResponse(response).
Amend the following block to:
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
Url = youtubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
youtubeUsage.fetch(Url);
}
Delete the try/catch from onCreate.
And no need to use SharedPreferences at all.
UPDATE
Try this code:
MyNetworkResponse.java
interface MyNetworkResponse {
void goodResponse(String responseString);
void badResponse(VolleyError error);
}
YoutubeUsage.java
class YoutubeUsage {
private RequestQueue queue;
private MyNetworkResponse callback;
YoutubeUsage(Object caller) {
this.callback = (MyNetworkResponse) caller;
queue = Volley.newRequestQueue((Context) caller);
}
static String getUrl(String signal) {
String playlistId = signal.substring(signal.indexOf("=") + 1);
return "https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails%2C%20snippet%2C%20id&playlistId=" + playlistId + "&maxResults=25&key=" + "API_KEY";
}
void fetch(String url){
StringRequest request = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
callback.goodResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.badResponse(error);
}
});
queue.add(request);
}
}
ConvertActivity.java
public class ConvertActivity extends AppCompatActivity implements MyNetworkResponse {
YoutubeUsage youtubeUsage;
ArrayList<String> videoIDs = new ArrayList<>();
ListView listView;
MyCustomAdapter myCustomAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_convert);
listView = findViewById(R.id.listview_convert);
youtubeUsage = new YoutubeUsage(this);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if ("android.intent.action.SEND".equals(action) && "text/plain".equals(type)) {
String url = YoutubeUsage.getUrl(Objects.requireNonNull(intent.getStringExtra("android.intent.extra.TEXT")));
youtubeUsage.fetch(url);
}
}
private ArrayList<String> getVideoIDs(String serverResponse) throws JSONException {
ArrayList<String> rawVideoIDs = new ArrayList<>();
JSONObject jsonObject = new JSONObject(serverResponse);
JSONArray jsonArray = jsonObject.getJSONArray("items");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
JSONObject jsonVideoId = jsonObject1.getJSONObject("contentDetails");
rawVideoIDs.add(jsonVideoId.getString("videoId"));
}
return rawVideoIDs;
}
private void createRecyclerView(ArrayList<String> videoIDs) {
myCustomAdapter = new MyCustomAdapter(this, videoIDs);
listView.setAdapter(myCustomAdapter);
myCustomAdapter.notifyDataSetChanged();
}
#Override
public void goodResponse(String responseString) {
Log.d("Convert:goodResp", "[" + responseString + "]");
try {
ArrayList<String> rawVideoIDs = getVideoIDs(responseString);
createRecyclerView(rawVideoIDs);
} catch (JSONException e) {
// handle JSONException, e.g. malformed response from server.
}
}
#Override
public void badResponse(VolleyError error) {
// handle unwanted server response.
}
}

Related

Added items from a places/photo api fetch to a recyclerview and the view is empty

I have been working on an app that requires me to get information such as a Place Name and a PLace Photo from google PLaces Api and set it into a RecyclerView. I am stuck because I managed to get the code to work with no errors but the RecyclerView is empty. What is wrong with my code?
I am stuck because I don't know where the problem is. When I run the code, all the fetchs work and the tags show up in the Log so I am completely lost. My first thought is that I am displaying the code wrong but then I have no recourse to step forward and change it to something else because I am not sure if it would be better or worse.
This is the Fragment for the RecyclerView Item:
public class VenueList extends Fragment{
ArrayList<VenueItem> vIL = new ArrayList<>();
private PlacesClient placesClient;
private Context contextForPlaces;
place ids for the places I am currently using
String[] clubs = {"ChIJO_uSYKNZwokRAC7RLeB0oZ8", "ChIJAQBEylJYwokRLbnrAchQImk",
"ChIJU_26rfpYwokRTNf2K1-7p8E", "ChIJ38hxfnhZwokRx1HSFLj790w", "ChIJBwnlGrdZwokRpf61pMm860c"
, "ChIJpSIzqrhZwokR1KnVMoVty_g", "ChIJMRV7375ZwokRAfltF6Y-wYw", "ChIJYabdHPhYwokRPmAV8GtM3gs",
"ChIJi2dSjQRZwokRuXUKcv4riVc", "ChIJKaKVI79ZwokRN8WicODOIAw", "ChIJwXI8Fb5ZwokRr4JjG4HxSP8",
"ChIJ6bU_E4ZZwokR2ZDbY_IhhrI"};
#Override
public void onAttach(Context context) {
super.onAttach(context);
contextForPlaces = context;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.menu_venue, container, false);
RecyclerView vRV = view.findViewById(R.id.view_venue);
List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.PHOTO_METADATAS);
if (!Places.isInitialized()) {
Places.initialize(contextForPlaces, "AIzaSyCKGd3fqmtsDklRGMhnkuIy1GS-j6gRBh8");}
placesClient = Places.createClient(contextForPlaces);
vRV.setHasFixedSize(true);
RecyclerView.LayoutManager vLM = new LinearLayoutManager(this.getActivity());
RecyclerView.Adapter vAdapter = new VenueAdapter(vIL);
// run through each photo to make sure it has a place attached to it then insert each photo and place into the vIL
//createBitmap for fetchPhoto
for (String club : clubs) {
FetchPlaceRequest request = FetchPlaceRequest.newInstance(club, placeFields);
placesClient.fetchPlace(request).addOnSuccessListener((response) -> {
Place place = response.getPlace();
PhotoMetadata photoMetadata = place.getPhotoMetadatas().get(0);
String attributions = photoMetadata.getAttributions();
FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata).setMaxHeight(200).build();
placesClient.fetchPhoto(photoRequest).addOnSuccessListener((fetchPhotoResponse) -> {
Bitmap bitmap = fetchPhotoResponse.getBitmap();
vIL.add(new VenueItem(/*Photo*/bitmap, place/*Name*/));
Log.i(TAG, "Photo Should Be Up: ");
}).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
int statusCode = apiException.getStatusCode();
// Handle error with given status code.
Log.e(TAG, "Place not found: " + exception.getMessage());
}
});
Log.i(TAG, "Place found: " + place.getName());
}).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
int statusCode = apiException.getStatusCode();
// Handle error with given status code.
Log.e(TAG, "Place not found: " + exception.getMessage());
}
});
}
vRV.setLayoutManager(vLM);
vRV.setAdapter(vAdapter);
return view;
}
This is the part of the RecyclerView Adapter I changed. I used to be a getResourse for the image because the image was from the drawable folder
public void onBindViewHolder(#NonNull VenueViewHolder venueViewHolder, int i) {
VenueItem currentItem = vIAL.get(i);
if(currentItem.getVenueImageResource() == null){
venueViewHolder.vIV.setImageResource(R.drawable.ic_android);
}else
venueViewHolder.vIV.setImageBitmap(currentItem.getVenueImageResource());
venueViewHolder.vTV.setText((CharSequence) currentItem.getVenueDescription());
}
The Item itself which I also had to change a bit from its original. I made the string a Place and the int a Bitmap. I thought that would work.
public class VenueItem {
private Bitmap venueImageResource;
private Place venueDescription;
public VenueItem(Bitmap vIR, Place description) {
venueImageResource = vIR;
venueDescription = description;
}
public Bitmap getVenueImageResource() {
return venueImageResource;
}
public Place getVenueDescription() {
return venueDescription;
}
}
I want to be able to request a place name and a photo of the place using the placesClient and precent it in the for of a RecyclerView. I know the place Ids are correct because the Log returns the names of all the places. But they do not show up on the RecyclerView
I figured out the answer myself.
vRV.setLayoutManager(vLM);
vRV.setAdapter(vAdapter);
I just had to put these two lines into the for loop under the list item so that each item could escape before meing erased

Error with Async_Http_Response_Handler

I am a beginner in Android development. I am developing an application which receives MySql data and then saves it in SQLite.
I am using Json for sync status so that i can show the the number unsync data as number of pending data to be synced.
The AsyncHttpResponseHandler is showing error in code as " Class 'Anonymous class derived from AsyncHttpResponseHandler method' onFailure(int, Header[], byte[],Throwable)' in 'AsyncHttpResponseHandler' ".
Now i am stuck with a problem in the code which i can't solve.
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
public class MainActivity extends AppCompatActivity {
// DB Class to perform DB related operations
DBController controller = new DBController(this);
// Progress Dialog Object
ProgressDialog prgDialog;
HashMap<String, String> queryValues;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get User records from SQLite DB
ArrayList<HashMap<String, String>> userList = controller.getAllUsers();
// If users exists in SQLite DB
if (userList.size() != 0) {
// Set the User Array list in ListView
ListAdapter adapter = new SimpleAdapter(MainActivity.this, userList, R.layout.view_logtable_entry, new String[] {
"id", "time","logtitle","log" }, new int[] { R.id.id, R.id.time, R.id.logtitle, R.id.log });
ListView myList = (ListView) findViewById(android.R.id.list);
myList.setAdapter(adapter);
}
// Initialize Progress Dialog properties
prgDialog = new ProgressDialog(this);
prgDialog.setMessage("Transferring Data. Please wait...");
prgDialog.setCancelable(false);
// BroadCase Receiver Intent Object
Intent alarmIntent = new Intent(getApplicationContext(), SampleBC.class);
// Pending Intent Object
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Alarm Manager Object
AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// Alarm Manager calls BroadCast for every Ten seconds (10 * 1000), BroadCase further calls service to check if new records are inserted in
// Remote MySQL DB
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 5000, 10 * 1000, pendingIntent);
}
// When Options Menu is selected
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here.
int id = item.getItemId();
// When Sync action button is clicked
if (id == R.id.refresh) {
// Transfer data from remote MySQL DB to SQLite on Android and perform Sync
syncSQLiteMySQLDB();
return true;
}
return super.onOptionsItemSelected(item);
}
// Method to Sync MySQL to SQLite DB
public void syncSQLiteMySQLDB() {
// Create AsycHttpClient object
AsyncHttpClient client = new AsyncHttpClient();
// Http Request Params Object
RequestParams params = new RequestParams();
// Show ProgressBar
prgDialog.show();
// Make Http call to getusers.php
client.post("http://example.com:3333/syncfolder/getusers.php", params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
// Hide ProgressBar
prgDialog.hide();
// Update SQLite DB with response sent by getusers.php
updateSQLite(response);
}
// When error occured
#Override
public void onFailure(int statusCode, Throwable error, String content) {
// TODO Auto-generated method stub
// Hide ProgressBar
prgDialog.hide();
if (statusCode == 404) {
Toast.makeText(getApplicationContext(), "Requested resource not found", Toast.LENGTH_LONG).show();
} else if (statusCode == 500) {
Toast.makeText(getApplicationContext(), "Something went wrong at server end", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet]",
Toast.LENGTH_LONG).show();
}
}
});
}
public void updateSQLite(String response){
ArrayList<HashMap<String, String>> usersynclist;
usersynclist = new ArrayList<HashMap<String, String>>();
// Create GSON object
Gson gson = new GsonBuilder().create();
try {
// Extract JSON array from the response
JSONArray arr = new JSONArray(response);
System.out.println(arr.length());
// If no of array elements is not zero
if(arr.length() != 0){
// Loop through each array element, get JSON object which has userid and username
for (int i = 0; i < arr.length(); i++) {
// Get JSON object
JSONObject obj = (JSONObject) arr.get(i);
System.out.println(obj.get("id"));
System.out.println(obj.get("time"));
System.out.println(obj.get("logtitle"));
System.out.println(obj.get("log"));
// DB QueryValues Object to insert into SQLite
queryValues = new HashMap<String, String>();
// Add userID extracted from Object
queryValues.put("id", obj.get("id").toString());
// Add userName extracted from Object
queryValues.put("time", obj.get("time").toString());
queryValues.put("logtitle", obj.get("logtitle").toString());
queryValues.put("log", obj.get("log").toString());
// Insert User into SQLite DB
controller.insertUser(queryValues);
HashMap<String, String> map = new HashMap<String, String>();
// Add status for each User in Hashmap
map.put("id", obj.get("id").toString());
map.put("status", "1");
usersynclist.add(map);
}
// Inform Remote MySQL DB about the completion of Sync activity by passing Sync status of Users
updateMySQLSyncSts(gson.toJson(usersynclist));
// Reload the Main Activity
reloadActivity();
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Method to inform remote MySQL DB about completion of Sync activity
public void updateMySQLSyncSts(String json) {
System.out.println(json);
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("syncstatus", json);
// Make Http call to updatesyncsts.php with JSON parameter which has Sync statuses of Users
client.post("http://example.com:3333/syncfolder/updatesyncsts.php", params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
Toast.makeText(getApplicationContext(), "MySQL DB has been informed about Sync activity", Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(int statusCode, Throwable error, String content) {
Toast.makeText(getApplicationContext(), "Error Occured", Toast.LENGTH_LONG).show();
}
});
}
// Reload MainActivity
public void reloadActivity() {
Intent objIntent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(objIntent);
}
}
you should change your method signature of
onSuccess(String response)
to
onSuccess(int responseCode, Header[] responseHeaders, String responseBody)

I want to create highchart widget by Eclipse RAP and i follow "RAP/Custom Widgets FAQ",but there is error?

i want to create some highchart widget by Eclipse RAP ,and i follow the official guide like this
handlejs:
var CKEDITOR_BASEPATH = "rwt-resources/";
(function(){
'use strict';
rap.registerTypeHandler( "rap.sunline.HighCharts", {
factory : function( properties ) {
var parent = rap.getObject( properties.parent );
// var element = document.createElement( "div" );
// parent.append( element );
// $(element).html("askldfjaskljdk");
return {};
}
});
}());
widget.java:
public class HightChartComposite extends Composite {
private static final String RESOURCES_PATH = "resources/";
private static final String REGISTER_PATH = "hightcharts/";
private static final String[] RESOURCE_FILES = { "jquery-2.1.0.min.js", "highcharts.js","ChartPaintListener.js" };
private static final String REMOTE_TYPE = "rap.sunline.HightCharts";
private final RemoteObject remoteObject;
private final OperationHandler operationHandler = new AbstractOperationHandler() {
#Override
public void handleSet(JsonObject properties) {
// JsonValue textValue = properties.get("text");
// if (textValue != null) {
// text = textValue.asString();
// }
}
};
public HightChartComposite(Composite parent, int style) {
super(parent, style);
registerResources();
loadJavaScript();
Connection connection = RWT.getUISession().getConnection();
remoteObject = connection.createRemoteObject(REMOTE_TYPE);
remoteObject.setHandler(operationHandler);
remoteObject.set("parent", WidgetUtil.getId(this));
}
private void registerResources() {
ResourceManager resourceManager = RWT.getResourceManager();
boolean isRegistered = resourceManager.isRegistered(REGISTER_PATH + RESOURCE_FILES[0]);
if (!isRegistered) {
try {
for (String fileName : RESOURCE_FILES) {
register(resourceManager, fileName);
}
} catch (IOException ioe) {
throw new IllegalArgumentException("Failed to load resources", ioe);
}
}
}
private void loadJavaScript() {
JavaScriptLoader jsLoader = RWT.getClient().getService(JavaScriptLoader.class);
ResourceManager resourceManager = RWT.getResourceManager();
jsLoader.require(resourceManager.getLocation(REGISTER_PATH + "jquery-2.1.0.min.js"));
jsLoader.require(resourceManager.getLocation(REGISTER_PATH + "highcharts.js"));
jsLoader.require(resourceManager.getLocation(REGISTER_PATH + "ChartPaintListener.js"));
}
private void register(ResourceManager resourceManager, String fileName) throws IOException {
ClassLoader classLoader = HightChartComposite.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(RESOURCES_PATH + fileName);
try {
resourceManager.register(REGISTER_PATH + fileName, inputStream);
} finally {
inputStream.close();
}
}
// //////////////////
// overwrite methods
#Override
public void setLayout(Layout layout) {
throw new UnsupportedOperationException("Cannot change internal layout of CkEditor");
}
}
the error is occur:
Uncaught Error: Operation "create" on target "r6" of type "null" failed:
No Handler for type rap.sunline.HightCharts
Properties:
parent = w5
and i have a question about this , what differents from extends Canvas and Composite;
You forget to implement setters in your javascript code.
The created object is stored by the framework under its object id. This object has to implement setter methods that match the properties defined in the handler, which will then be called when the server sends a set operation for a given property.

WebClient event firing order

I'm new to WP7 app development and I'm having trouble passing parameters to an API on a website.
It's my understanding that the onNavigatedTo() is fired first when a page is open on the WP7, however when I try to grab the parameters the webClient_DownloadStringCompleted() is fired first.
public partial class Ranks : PhoneApplicationPage
{
private WebClient webClient;
private string pageType;
private string pagePosition;
public Ranks()
{
InitializeComponent();
this.webClient = new WebClient();
string header_auth = "application/json";
this.webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
this.webClient.Headers[HttpRequestHeader.Authorization] = header_auth;
Uri serviceUri = new Uri(#"http://www.example.com/api/API.php?type=" + pageType + "&position=" + pagePosition);
this.webClient.DownloadStringAsync(serviceUri);
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
string type, position;
if (NavigationContext.QueryString.TryGetValue("type", out type))
{
pageType = type;
}
if (NavigationContext.QueryString.TryGetValue("pos", out position))
{
pagePosition = position;
}
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string myJsonString = e.Result;
List<PlayerDetails> dataSource = new List<PlayerDetails>();
//load into memory stream
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(myJsonString)))
{
//parse into jsonser
var ser = new DataContractJsonSerializer(typeof(PlayerDetails[]));
PlayerDetails[] obj = (PlayerDetails[])ser.ReadObject(ms);
foreach (PlayerDetails plyr in obj)
{
dataSource.Add(plyr);
}
playerList.ItemsSource = dataSource;
}
}
Whenever the URI string is built it's missing the parameters 'pageType' and 'pagePosition'
Any help would be greatly appreciated!
The class constructor will always get called before OnNavigatedTo. you should move that code from the constructor, and into OnNavigatedTo (or Loaded).
I'm guessing that you have that code in the constructor because you only want it to happen once per page load (i.e. not when the user navigates Back onto the page). If that's the case, you can check the NavigationMode.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.New)
{
string type, position;
if (NavigationContext.QueryString.TryGetValue("type", out type))
{
pageType = type;
}
if (NavigationContext.QueryString.TryGetValue("pos", out position))
{
pagePosition = position;
}
this.webClient = new WebClient();
string header_auth = "application/json";
this.webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
this.webClient.Headers[HttpRequestHeader.Authorization] = header_auth;
Uri serviceUri = new Uri(#"http://www.example.com/api/API.php?type=" + pageType + "&position=" + pagePosition);
this.webClient.DownloadStringAsync(serviceUri);
}
}

Ehcache hangs in test

I am in the process of rewriting a bottle neck in the code of the project I am on, and in doing so I am creating a top level item that contains a self populating Ehcache. I am attempting to write a test to make sure that the basic call chain is established, but when the test executes it hands when retrieving the item from the cache.
Here are the Setup and the test, for reference mocking is being done with Mockito:
#Before
public void SetUp()
{
testCache = new Cache(getTestCacheConfiguration());
recordingFactory = new EntryCreationRecordingCache();
service = new Service<Request, Response>(testCache, recordingFactory);
}
#Test
public void retrievesResultsFromSuppliedCache()
{
ResultType resultType = mock(ResultType.class);
Response expectedResponse = mock(Response.class);
addToExpectedResults(resultType, expectedResponse);
Request request = mock(Request.class);
when(request.getResultType()).thenReturn(resultType);
assertThat(service.getResponse(request), sameInstance(expectedResponse));
assertTrue(recordingFactory.requestList.contains(request));
}
private void addToExpectedResults(ResultType resultType,
Response response) {
recordingFactory.responseMap.put(resultType, response);
}
private CacheConfiguration getTestCacheConfiguration() {
CacheConfiguration cacheConfiguration = new CacheConfiguration("TEST_CACHE", 10);
cacheConfiguration.setLoggingEnabled(false);
return cacheConfiguration;
}
private class EntryCreationRecordingCache extends ResponseFactory{
public final Map<ResultType, Response> responseMap = new ConcurrentHashMap<ResultType, Response>();
public final List<Request> requestList = new ArrayList<Request>();
#Override
protected Map<ResultType, Response> generateResponse(Request request) {
requestList.add(request);
return responseMap;
}
}
Here is the ServiceClass
public class Service<K extends Request, V extends Response> {
private Ehcache cache;
public Service(Ehcache cache, ResponseFactory factory) {
this.cache = new SelfPopulatingCache(cache, factory);
}
#SuppressWarnings("unchecked")
public V getResponse(K request)
{
ResultType resultType = request.getResultType();
Element cacheEntry = cache.get(request);
V response = null;
if(cacheEntry != null){
Map<ResultType, Response> resultTypeMap = (Map<ResultType, Response>) cacheEntry.getValue();
try{
response = (V) resultTypeMap.get(resultType);
}catch(NullPointerException e){
throw new RuntimeException("Result type not found for Result Type: " + resultType);
}catch(ClassCastException e){
throw new RuntimeException("Incorrect Response Type for Result Type: " + resultType);
}
}
return response;
}
}
And here is the ResponseFactory:
public abstract class ResponseFactory implements CacheEntryFactory{
#Override
public final Object createEntry(Object request) throws Exception {
return generateResponse((Request)request);
}
protected abstract Map<ResultType,Response> generateResponse(Request request);
}
After wrestling with it for a while, I discovered that the cache wasn't being initialized. Creating a CacheManager and adding the cache to it resolved the problem.
I also had a problem with EHCache hanging, although only in a hello-world example. Adding this to the end fixed it (the application ends normally).
CacheManager.getInstance().removeAllCaches();
https://stackoverflow.com/a/20731502/2736496